mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-14 23:34:08 +00:00
libobs: Use uthash for properties
This commit is contained in:
parent
eff3cf134c
commit
78aa4e03dc
|
@ -191,16 +191,16 @@ struct obs_property {
|
|||
obs_property_modified_t modified;
|
||||
obs_property_modified2_t modified2;
|
||||
|
||||
struct obs_property *next;
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
struct obs_properties {
|
||||
void *param;
|
||||
void (*destroy)(void *param);
|
||||
uint32_t flags;
|
||||
uint32_t groups;
|
||||
|
||||
struct obs_property *first_property;
|
||||
struct obs_property **last;
|
||||
struct obs_property *properties;
|
||||
struct obs_property *parent;
|
||||
};
|
||||
|
||||
|
@ -208,7 +208,6 @@ obs_properties_t *obs_properties_create(void)
|
|||
{
|
||||
struct obs_properties *props;
|
||||
props = bzalloc(sizeof(struct obs_properties));
|
||||
props->last = &props->first_property;
|
||||
return props;
|
||||
}
|
||||
|
||||
|
@ -277,15 +276,14 @@ static void obs_property_destroy(struct obs_property *property)
|
|||
void obs_properties_destroy(obs_properties_t *props)
|
||||
{
|
||||
if (props) {
|
||||
struct obs_property *p = props->first_property;
|
||||
struct obs_property *p, *tmp;
|
||||
|
||||
if (props->destroy && props->param)
|
||||
props->destroy(props->param);
|
||||
|
||||
while (p) {
|
||||
struct obs_property *next = p->next;
|
||||
HASH_ITER (hh, props->properties, p, tmp) {
|
||||
HASH_DEL(props->properties, p);
|
||||
obs_property_destroy(p);
|
||||
p = next;
|
||||
}
|
||||
|
||||
bfree(props);
|
||||
|
@ -294,31 +292,32 @@ void obs_properties_destroy(obs_properties_t *props)
|
|||
|
||||
obs_property_t *obs_properties_first(obs_properties_t *props)
|
||||
{
|
||||
return (props != NULL) ? props->first_property : NULL;
|
||||
return (props != NULL) ? props->properties : NULL;
|
||||
}
|
||||
|
||||
obs_property_t *obs_properties_get(obs_properties_t *props, const char *name)
|
||||
{
|
||||
struct obs_property *property;
|
||||
struct obs_property *property, *tmp;
|
||||
|
||||
if (!props)
|
||||
return NULL;
|
||||
|
||||
property = props->first_property;
|
||||
while (property) {
|
||||
if (strcmp(property->name, name) == 0)
|
||||
return property;
|
||||
HASH_FIND_STR(props->properties, name, property);
|
||||
if (property)
|
||||
return property;
|
||||
|
||||
if (property->type == OBS_PROPERTY_GROUP) {
|
||||
obs_properties_t *group =
|
||||
obs_property_group_content(property);
|
||||
obs_property_t *found = obs_properties_get(group, name);
|
||||
if (found != NULL) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
if (!props->groups)
|
||||
return NULL;
|
||||
|
||||
property = property->next;
|
||||
/* Recursively check groups as well, if any */
|
||||
HASH_ITER (hh, props->properties, property, tmp) {
|
||||
if (property->type != OBS_PROPERTY_GROUP)
|
||||
continue;
|
||||
|
||||
obs_properties_t *group = obs_property_group_content(property);
|
||||
obs_property_t *found = obs_properties_get(group, name);
|
||||
if (found)
|
||||
return found;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -334,51 +333,29 @@ void obs_properties_remove_by_name(obs_properties_t *props, const char *name)
|
|||
if (!props)
|
||||
return;
|
||||
|
||||
/* obs_properties_t is a forward-linked-list, so we need to keep both
|
||||
* previous and current pointers around. That way we can fix up the
|
||||
* pointers for the previous element if we find a match.
|
||||
*/
|
||||
struct obs_property *cur = props->first_property;
|
||||
struct obs_property *prev = props->first_property;
|
||||
struct obs_property *cur, *tmp;
|
||||
|
||||
while (cur) {
|
||||
if (strcmp(cur->name, name) == 0) {
|
||||
// Fix props->last pointer.
|
||||
if (props->last == &cur->next) {
|
||||
if (cur == prev) {
|
||||
// If we are the last entry and there
|
||||
// is no previous entry, reset.
|
||||
props->last = &props->first_property;
|
||||
} else {
|
||||
// If we are the last entry and there
|
||||
// is a previous entry, update.
|
||||
props->last = &prev->next;
|
||||
}
|
||||
}
|
||||
HASH_FIND_STR(props->properties, name, cur);
|
||||
|
||||
// Fix props->first_property.
|
||||
if (props->first_property == cur)
|
||||
props->first_property = cur->next;
|
||||
if (cur) {
|
||||
HASH_DELETE(hh, props->properties, cur);
|
||||
|
||||
// Update the previous element next pointer with our
|
||||
// next pointer. This is an automatic no-op if both
|
||||
// elements alias the same memory.
|
||||
prev->next = cur->next;
|
||||
if (cur->type == OBS_PROPERTY_GROUP)
|
||||
props->groups--;
|
||||
|
||||
// Finally clear our own next pointer and destroy.
|
||||
cur->next = NULL;
|
||||
obs_property_destroy(cur);
|
||||
obs_property_destroy(cur);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
if (!props->groups)
|
||||
return;
|
||||
|
||||
if (cur->type == OBS_PROPERTY_GROUP) {
|
||||
obs_properties_remove_by_name(
|
||||
obs_property_group_content(cur), name);
|
||||
}
|
||||
HASH_ITER (hh, props->properties, cur, tmp) {
|
||||
if (cur->type != OBS_PROPERTY_GROUP)
|
||||
continue;
|
||||
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
obs_properties_remove_by_name(obs_property_group_content(cur),
|
||||
name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,10 +363,9 @@ void obs_properties_apply_settings_internal(obs_properties_t *props,
|
|||
obs_data_t *settings,
|
||||
obs_properties_t *realprops)
|
||||
{
|
||||
struct obs_property *p;
|
||||
struct obs_property *p, *tmp;
|
||||
|
||||
p = props->first_property;
|
||||
while (p) {
|
||||
HASH_ITER (hh, props->properties, p, tmp) {
|
||||
if (p->type == OBS_PROPERTY_GROUP) {
|
||||
obs_properties_apply_settings_internal(
|
||||
obs_property_group_content(p), settings,
|
||||
|
@ -399,7 +375,6 @@ void obs_properties_apply_settings_internal(obs_properties_t *props,
|
|||
p->modified(realprops, p, settings);
|
||||
else if (p->modified2)
|
||||
p->modified2(p->priv, realprops, p, settings);
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -414,13 +389,6 @@ void obs_properties_apply_settings(obs_properties_t *props,
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static inline void propertes_add(struct obs_properties *props,
|
||||
struct obs_property *p)
|
||||
{
|
||||
*props->last = p;
|
||||
props->last = &p->next;
|
||||
}
|
||||
|
||||
static inline size_t get_property_size(enum obs_property_type type)
|
||||
{
|
||||
switch (type) {
|
||||
|
@ -471,7 +439,8 @@ static inline struct obs_property *new_prop(struct obs_properties *props,
|
|||
p->type = type;
|
||||
p->name = bstrdup(name);
|
||||
p->desc = bstrdup(desc);
|
||||
propertes_add(props, p);
|
||||
|
||||
HASH_ADD_STR(props->properties, name, p);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -489,22 +458,22 @@ static inline obs_properties_t *get_topmost_parent(obs_properties_t *props)
|
|||
|
||||
static inline bool contains_prop(struct obs_properties *props, const char *name)
|
||||
{
|
||||
struct obs_property *p = props->first_property;
|
||||
struct obs_property *p, *tmp;
|
||||
HASH_FIND_STR(props->properties, name, p);
|
||||
|
||||
while (p) {
|
||||
if (strcmp(p->name, name) == 0) {
|
||||
blog(LOG_WARNING, "Property '%s' exists", name);
|
||||
if (p) {
|
||||
blog(LOG_WARNING, "Property '%s' exists", name);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!props->groups)
|
||||
return false;
|
||||
|
||||
HASH_ITER (hh, props->properties, p, tmp) {
|
||||
if (p->type != OBS_PROPERTY_GROUP)
|
||||
continue;
|
||||
if (contains_prop(obs_property_group_content(p), name))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p->type == OBS_PROPERTY_GROUP) {
|
||||
if (contains_prop(obs_property_group_content(p),
|
||||
name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -753,24 +722,23 @@ static bool check_property_group_recursion(obs_properties_t *parent,
|
|||
obs_properties_t *group)
|
||||
{
|
||||
/* Scan the group for the parent. */
|
||||
obs_property_t *current_property = group->first_property;
|
||||
while (current_property) {
|
||||
if (current_property->type == OBS_PROPERTY_GROUP) {
|
||||
obs_properties_t *cprops =
|
||||
obs_property_group_content(current_property);
|
||||
if (cprops == parent) {
|
||||
/* Contains find_props */
|
||||
return true;
|
||||
} else if (cprops == group) {
|
||||
/* Contains self, shouldn't be possible but
|
||||
* lets verify anyway. */
|
||||
return true;
|
||||
}
|
||||
if (check_property_group_recursion(parent, cprops))
|
||||
return true;
|
||||
}
|
||||
obs_property_t *p, *tmp;
|
||||
|
||||
current_property = current_property->next;
|
||||
HASH_ITER (hh, group->properties, p, tmp) {
|
||||
if (p->type != OBS_PROPERTY_GROUP)
|
||||
continue;
|
||||
|
||||
obs_properties_t *cprops = obs_property_group_content(p);
|
||||
if (cprops == parent) {
|
||||
/* Contains find_props */
|
||||
return true;
|
||||
} else if (cprops == group) {
|
||||
/* Contains self, shouldn't be possible but
|
||||
* lets verify anyway. */
|
||||
return true;
|
||||
}
|
||||
if (check_property_group_recursion(parent, cprops))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -779,13 +747,11 @@ static bool check_property_group_recursion(obs_properties_t *parent,
|
|||
static bool check_property_group_duplicates(obs_properties_t *parent,
|
||||
obs_properties_t *group)
|
||||
{
|
||||
obs_property_t *current_property = group->first_property;
|
||||
while (current_property) {
|
||||
if (has_prop(parent, current_property->name)) {
|
||||
return true;
|
||||
}
|
||||
obs_property_t *p, *tmp;
|
||||
|
||||
current_property = current_property->next;
|
||||
HASH_ITER (hh, group->properties, p, tmp) {
|
||||
if (has_prop(parent, p->name))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -812,6 +778,7 @@ obs_property_t *obs_properties_add_group(obs_properties_t *props,
|
|||
return NULL;
|
||||
|
||||
obs_property_t *p = new_prop(props, name, desc, OBS_PROPERTY_GROUP);
|
||||
props->groups++;
|
||||
group->parent = p;
|
||||
|
||||
struct group_data *data = get_property_data(p);
|
||||
|
@ -849,7 +816,7 @@ bool obs_property_next(obs_property_t **p)
|
|||
if (!p || !*p)
|
||||
return false;
|
||||
|
||||
*p = (*p)->next;
|
||||
*p = (*p)->hh.next;
|
||||
return *p != NULL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue