gstvalue: generalize gst_value_is_subset()
- Add case where we have element in subset that are equal to element in superset. In this case subset is still a subset if at least one element is a subset of the corresponding element in superset. - clarify gst_value_is_subset inline documentation - Add helper VALUE_TYPE_SINGLETON (type) to identify GType that represent a value that is not a collection. - Fixed issue in gst_value_is_subset_array_array (<1, 2, 3>, <0, 1, 4, 2, 3>) would have returned TRUE because because the alignment of the subset could be done multiple times. Now once alignment of set as been done once, everything else in the superset need to be a subset of corresponding element without interuption. is_subset (<1, 2, 3>, <0, 1, 2, 3>) => TRUE, but is_subset (<1, 2, 3>, <0, 1, 4, 2, 3>) => FALSE. - If both array are fixed value and we perform a is_subset on them, both value can't be equal to be considered subset. (For consistency with other fixed values) - Define gst_value_subtract (singleton, array) and gst_value_subtract (array, singleton), to allow a gst_value_is_subset (singleton, array) and gst_value_is_subset (array, singleton). General case of gst_value_is_subset (v1, v2) use gst_value_subtract (v1, v2) and gst_value_subtract (v2, v1) to evaluate _is_subset(), therefore we need these for is_subset() operation that involve singleton and array. Note gst_value_subtract (array, array) is not implemented but this case is not require by gst_value_is_subset () and as it has a direct handling. Warned if the case is used. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/9220>
This commit is contained in:
parent
39a7e0066c
commit
93241e4203
@ -60012,10 +60012,10 @@ ranges) value.</doc>
|
||||
</parameters>
|
||||
</function>
|
||||
<function name="value_is_subset" c:identifier="gst_value_is_subset">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.c">Check that @value1 is a subset of @value2.</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.c">Check that @value1 is a proper subset of @value2.</doc>
|
||||
<source-position filename="../subprojects/gstreamer/gst/gstvalue.h"/>
|
||||
<return-value transfer-ownership="none">
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.c">%TRUE is @value1 is a subset of @value2</doc>
|
||||
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstvalue.c">%TRUE is @value1 is a proper subset of @value2</doc>
|
||||
<type name="gboolean" c:type="gboolean"/>
|
||||
</return-value>
|
||||
<parameters>
|
||||
|
@ -4516,33 +4516,60 @@ gst_value_is_subset_array_array (const GValue * val_sub, const GValue * val_sup)
|
||||
{
|
||||
/* Check if each element of the subset is within the subset while
|
||||
* respecting order. Not all element of superset has to be present in
|
||||
* subset.*/
|
||||
* subset. If at least one element in val_sub is a subset of the corresponding
|
||||
* element in val_sup, and other elements of val_sub are equal to
|
||||
* corresponding elements of val_sup then val_sub is still a subset of val_sup
|
||||
*/
|
||||
|
||||
GstValueList *superset = VALUE_LIST_ARRAY (val_sup);
|
||||
GstValueList *subset = VALUE_LIST_ARRAY (val_sub);
|
||||
gint it1, it2, len1, len2;
|
||||
gboolean is_subset;
|
||||
gboolean is_subset, is_equal = FALSE;
|
||||
gsize subset_count = 0;
|
||||
gsize equal_count = 0;
|
||||
|
||||
len2 = superset->len;
|
||||
len1 = subset->len;
|
||||
is_subset = len1 <= len2;
|
||||
|
||||
for (it1 = 0, it2 = 0; is_subset && it1 < len1; it1++, it2++) {
|
||||
for (it1 = 0, it2 = 0; (is_subset || is_equal) && it1 < len1; it1++, it2++) {
|
||||
const GValue *child1 = &subset->fields[it1];
|
||||
const GValue *child2 = &superset->fields[it2];
|
||||
|
||||
is_subset = gst_value_is_subset (child1, child2);
|
||||
if (is_subset == FALSE) {
|
||||
is_equal = gst_value_compare (child1, child2) == GST_VALUE_EQUAL;
|
||||
if (is_equal)
|
||||
equal_count++;
|
||||
else if ((is_subset = gst_value_is_subset (child1, child2)))
|
||||
subset_count++;
|
||||
else if (subset_count == 0 && equal_count == 0) {
|
||||
/* try to find an element in superset that is a superset of subset[it1] */
|
||||
for (it2 = it2 + 1; it2 < len2 && it2 + len1 <= len2; it2++) {
|
||||
child2 = &superset->fields[it2];
|
||||
if ((is_subset = gst_value_is_subset (child1, child2)) == TRUE)
|
||||
if (gst_value_compare (child1, child2) == GST_VALUE_EQUAL) {
|
||||
is_equal = TRUE;
|
||||
equal_count++;
|
||||
break;
|
||||
} else if ((is_subset = gst_value_is_subset (child1, child2))) {
|
||||
subset_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return is_subset;
|
||||
if (is_equal || is_subset) {
|
||||
if (gst_value_is_fixed (val_sup) && gst_value_is_fixed (val_sub)) {
|
||||
/* With two fixed array we don't allow both array to be equal for
|
||||
* consistency with other is_subset operation on other fixed values */
|
||||
return subset_count > 0;
|
||||
} else {
|
||||
|
||||
/* For un-fixed value we consider equal value to be a subset */
|
||||
return TRUE;
|
||||
}
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4551,9 +4578,11 @@ gst_value_is_subset_array_array (const GValue * val_sub, const GValue * val_sup)
|
||||
* @value1: a #GValue
|
||||
* @value2: a #GValue
|
||||
*
|
||||
* Check that @value1 is a subset of @value2.
|
||||
* Check that @value1 is a subset of @value2. If @value1 and @value2 is are
|
||||
* fixed value, value1 must be a subset of value2 and not equal to @value2 to
|
||||
* be a subset of @value2.
|
||||
*
|
||||
* Return: %TRUE is @value1 is a subset of @value2
|
||||
* Return: %TRUE is @value1 is a subset, strict subset if both values are of @value2
|
||||
*/
|
||||
gboolean
|
||||
gst_value_is_subset (const GValue * value1, const GValue * value2)
|
||||
@ -4588,23 +4617,38 @@ gst_value_is_subset (const GValue * value1, const GValue * value2)
|
||||
}
|
||||
|
||||
/*
|
||||
* First (superset - subset) needs to return a non-empty set, second
|
||||
* (subset - superset) needs to give an empty set. Requiring (subset - superset)
|
||||
* to give an empty set enforce a subset (value1) to be a proper/strict
|
||||
* subset of the superset (value2).
|
||||
*
|
||||
* Example with range:
|
||||
* subset = [1, 2]
|
||||
* superset = 1
|
||||
* 1 - [1,2] = empty
|
||||
* -> !subset
|
||||
*
|
||||
* Example with range:
|
||||
* subset = 1
|
||||
* superset = [1, 2]
|
||||
* [1,2] - 1 = 2
|
||||
* -> 1 - [1,2] = empty
|
||||
* and 1 - [1,2] = empty
|
||||
* -> subset
|
||||
*
|
||||
* Example with range:
|
||||
* subset = [1, 2]
|
||||
* superset = [1, 3]
|
||||
* [1,3] - [1,2] = 3
|
||||
* -> [1,2] - [1,3] = empty
|
||||
* -> subset
|
||||
* and [1,2] - [1,3] = empty
|
||||
* -> subset
|
||||
*
|
||||
* {1,2} - {1,3} = 2
|
||||
* -> {1,3} - {1,2} = 3
|
||||
* -> !subset
|
||||
* Example with list:
|
||||
* subset: {1, 3}
|
||||
* superset: {1, 2}
|
||||
* {1,2} - {1,3} = empty
|
||||
* and {1,3} - {1,2} = 3
|
||||
* -> !subset
|
||||
*
|
||||
* First caps subtraction needs to return a non-empty set, second
|
||||
* subtractions needs to give en empty set.
|
||||
* Both substractions are switched below, as it's faster that way.
|
||||
*/
|
||||
if (!gst_value_subtract (NULL, value1, value2)) {
|
||||
@ -5913,6 +5957,94 @@ gst_value_subtract_list (GValue * dest, const GValue * minuend,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to handle subtraction cases where the minuend is a
|
||||
* GST_TYPE_ARRAY. The implementation is limited to subtrahends of fixed types.
|
||||
*
|
||||
* NOTE: Current use case is gst_value_is_subset () where only one of the
|
||||
* GValue is a GST_TYPE_ARRAY. For these use cases gst_value_is_subset ()
|
||||
* uses subtractions to evaluate if a value is a subset of another value.
|
||||
*/
|
||||
static gboolean
|
||||
gst_value_subtract_from_array (GValue * dest,
|
||||
const GValue * minuend, const GValue * subtrahend)
|
||||
{
|
||||
GstValueList *m = VALUE_LIST_ARRAY (minuend);
|
||||
gint it;
|
||||
gint consumed = FALSE;
|
||||
gboolean dest_init = FALSE;
|
||||
GType stype = G_VALUE_TYPE (subtrahend);
|
||||
|
||||
if (stype != GST_TYPE_ARRAY && gst_type_is_fixed (stype)) {
|
||||
for (it = 0; it < m->len; it++) {
|
||||
const GValue *child = &m->fields[it];
|
||||
|
||||
if (G_VALUE_TYPE (child) == stype) {
|
||||
if (!consumed && gst_value_compare (subtrahend, child) ==
|
||||
GST_VALUE_EQUAL) {
|
||||
consumed = TRUE;
|
||||
continue;
|
||||
} else if (dest) {
|
||||
if (!dest_init) {
|
||||
g_value_init (dest, G_TYPE_ARRAY);
|
||||
dest_init = TRUE;
|
||||
}
|
||||
gst_value_array_append_value (dest, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (consumed && m->len == 1) {
|
||||
if (dest_init)
|
||||
g_value_unset (dest);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
} else {
|
||||
g_warning ("not implemented");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to handle subtraction cases where the subtrahend is a
|
||||
* GST_TYPE_ARRAY. The implementation is limited to minuends of fixed types.
|
||||
*
|
||||
* NOTE: Current use case is gst_value_is_subset () where only one of the
|
||||
* GValue is a GST_TYPE_ARRAY. For these use cases gst_value_is_subset ()
|
||||
* uses subtractions to evaluate if a value is a subset of another value.
|
||||
*/
|
||||
static gboolean
|
||||
gst_value_subtract_array (GValue * dest, const GValue * minuend,
|
||||
const GValue * subtrahend)
|
||||
{
|
||||
GstValueList *s = VALUE_LIST_ARRAY (subtrahend);
|
||||
gint it;
|
||||
GType mtype = G_VALUE_TYPE (minuend);
|
||||
|
||||
if (mtype != GST_TYPE_ARRAY && gst_type_is_fixed (mtype)) {
|
||||
|
||||
for (it = 0; it < s->len; it++) {
|
||||
const GValue *child = &s->fields[it];
|
||||
|
||||
if (G_VALUE_TYPE (child) == mtype) {
|
||||
if (gst_value_compare (minuend, child) == GST_VALUE_EQUAL)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (dest)
|
||||
gst_value_init_and_copy (dest, minuend);
|
||||
} else {
|
||||
g_warning ("not implemented");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_value_subtract_fraction_fraction_range (GValue * dest,
|
||||
const GValue * minuend, const GValue * subtrahend)
|
||||
@ -6574,6 +6706,14 @@ gst_value_subtract (GValue * dest, const GValue * minuend,
|
||||
if (stype == GST_TYPE_LIST)
|
||||
return gst_value_subtract_list (dest, minuend, subtrahend);
|
||||
|
||||
if (mtype == GST_TYPE_ARRAY && stype != GST_TYPE_ARRAY &&
|
||||
gst_type_is_fixed (stype))
|
||||
return gst_value_subtract_from_array (dest, minuend, subtrahend);
|
||||
|
||||
if (stype == GST_TYPE_ARRAY && mtype != GST_TYPE_ARRAY &&
|
||||
gst_type_is_fixed (mtype))
|
||||
return gst_value_subtract_array (dest, minuend, subtrahend);
|
||||
|
||||
len = gst_value_subtract_funcs->len;
|
||||
for (i = 0; i < len; i++) {
|
||||
info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i);
|
||||
|
Loading…
x
Reference in New Issue
Block a user