diff --git a/libobs/obs-properties.c b/libobs/obs-properties.c index 397d93416..ab683ed1d 100644 --- a/libobs/obs-properties.c +++ b/libobs/obs-properties.c @@ -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; }