libobs: Fix obs_data_apply
obs_data_apply is used to apply the changes of a source object in to a destination object. Problem with this however is that if sub-objects are in use, it currently just copies the pointer of the sub-object, meaning that the source and destination will both share the same sub-object via reference. If anything modifies that sub-object data, it'll modify it for both objects, which was not intended. Instead of copying the object pointer, create a new copy and then recursively repeat the process to ensure the data is always completely separate.
This commit is contained in:
parent
aabb911e9f
commit
b042e20e24
@ -798,12 +798,63 @@ static inline void set_item_auto(struct obs_data *data, obs_data_item_t **item,
|
||||
set_item_data(data, item, name, ptr, size, type, false, true);
|
||||
}
|
||||
|
||||
static void copy_obj(struct obs_data *data, const char *name,
|
||||
struct obs_data *obj,
|
||||
void (*callback)(obs_data_t *, const char *, obs_data_t *))
|
||||
{
|
||||
if (obj) {
|
||||
obs_data_t *new_obj = obs_data_create();
|
||||
obs_data_apply(new_obj, obj);
|
||||
callback(data, name, new_obj);
|
||||
obs_data_release(new_obj);
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_array(struct obs_data *data, const char *name,
|
||||
struct obs_data_array *array,
|
||||
void (*callback)(obs_data_t*, const char*, obs_data_array_t*))
|
||||
{
|
||||
if (array) {
|
||||
obs_data_array_t *new_array = obs_data_array_create();
|
||||
da_reserve(new_array->objects, array->objects.num);
|
||||
|
||||
for (size_t i = 0; i < array->objects.num; i++) {
|
||||
obs_data_t *new_obj = obs_data_create();
|
||||
obs_data_t *obj = array->objects.array[i];
|
||||
|
||||
obs_data_apply(new_obj, obj);
|
||||
obs_data_array_push_back(new_array, new_obj);
|
||||
|
||||
obs_data_release(new_obj);
|
||||
}
|
||||
|
||||
callback(data, name, new_array);
|
||||
obs_data_array_release(new_array);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void copy_item(struct obs_data *data, struct obs_data_item *item)
|
||||
{
|
||||
const char *name = get_item_name(item);
|
||||
void *ptr = get_item_data(item);
|
||||
|
||||
set_item(data, NULL, name, ptr, item->data_len, item->type);
|
||||
if (item->type == OBS_DATA_OBJECT) {
|
||||
obs_data_t **obj = item->data_size ? ptr : NULL;
|
||||
|
||||
if (obj)
|
||||
copy_obj(data, name, *obj, obs_data_set_obj);
|
||||
|
||||
} else if (item->type == OBS_DATA_ARRAY) {
|
||||
obs_data_array_t **array = item->data_size ? ptr : NULL;
|
||||
|
||||
if (array)
|
||||
copy_array(data, name, *array, obs_data_set_array);
|
||||
|
||||
} else {
|
||||
if (item->data_size)
|
||||
set_item(data, NULL, name, ptr, item->data_size,
|
||||
item->type);
|
||||
}
|
||||
}
|
||||
|
||||
void obs_data_apply(obs_data_t *target, obs_data_t *apply_data)
|
||||
|
Loading…
x
Reference in New Issue
Block a user