17 * Boston, MA 02111-1307, USA. |
17 * Boston, MA 02111-1307, USA. |
18 */ |
18 */ |
19 |
19 |
20 /** |
20 /** |
21 * SECTION:gstvalue |
21 * SECTION:gstvalue |
22 * @short_description: GValue implementations specific |
22 * @short_description: GValue and GParamSpec implementations specific |
23 * to GStreamer |
23 * to GStreamer |
24 * |
24 * |
25 * GValue implementations specific to GStreamer. |
25 * GValue and GParamSpec implementations specific to GStreamer. |
26 * |
26 * |
27 * Note that operations on the same GstValue (or GValue) from multiple |
27 * Note that operations on the same GstValue (or GValue) from multiple |
28 * threads may lead to undefined behaviour. |
28 * threads may lead to undefined behaviour. |
29 * |
29 * |
30 * Last reviewed on 2008-03-11 (0.10.18) |
30 * Last reviewed on 2006-03-07 (0.10.4) |
31 */ |
31 */ |
32 |
32 |
33 #ifdef HAVE_CONFIG_H |
33 #ifdef HAVE_CONFIG_H |
34 #include "config.h" |
34 #include "config.h" |
35 #endif |
35 #endif |
69 GType minuend; |
69 GType minuend; |
70 GType subtrahend; |
70 GType subtrahend; |
71 GstValueSubtractFunc func; |
71 GstValueSubtractFunc func; |
72 }; |
72 }; |
73 |
73 |
74 #define FUNDAMENTAL_TYPE_ID_MAX \ |
|
75 (G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) |
|
76 #define FUNDAMENTAL_TYPE_ID(type) \ |
|
77 ((type) >> G_TYPE_FUNDAMENTAL_SHIFT) |
|
78 |
|
79 static GArray *gst_value_table; |
74 static GArray *gst_value_table; |
80 static GHashTable *gst_value_hash; |
|
81 static GstValueTable *gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID_MAX + 1]; |
|
82 static GArray *gst_value_union_funcs; |
75 static GArray *gst_value_union_funcs; |
83 static GArray *gst_value_intersect_funcs; |
76 static GArray *gst_value_intersect_funcs; |
84 static GArray *gst_value_subtract_funcs; |
77 static GArray *gst_value_subtract_funcs; |
85 |
78 |
86 /* Forward declarations */ |
79 /* Forward declarations */ |
88 static gchar *gst_value_serialize_fraction (const GValue * value); |
81 static gchar *gst_value_serialize_fraction (const GValue * value); |
89 |
82 |
90 static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1); |
83 static GstValueCompareFunc gst_value_get_compare_func (const GValue * value1); |
91 static gint gst_value_compare_with_func (const GValue * value1, |
84 static gint gst_value_compare_with_func (const GValue * value1, |
92 const GValue * value2, GstValueCompareFunc compare); |
85 const GValue * value2, GstValueCompareFunc compare); |
93 |
|
94 static gchar *gst_string_wrap (const gchar * s); |
|
95 static gchar *gst_string_take_and_wrap (gchar * s); |
|
96 static gchar *gst_string_unwrap (const gchar * s); |
|
97 |
|
98 static inline GstValueTable * |
|
99 gst_value_hash_lookup_type (GType type) |
|
100 { |
|
101 if (G_LIKELY (G_TYPE_IS_FUNDAMENTAL (type))) |
|
102 return gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)]; |
|
103 else |
|
104 return g_hash_table_lookup (gst_value_hash, (gpointer) type); |
|
105 } |
|
106 |
|
107 static void |
|
108 gst_value_hash_add_type (GType type, const GstValueTable * table) |
|
109 { |
|
110 if (G_TYPE_IS_FUNDAMENTAL (type)) |
|
111 gst_value_tables_fundamental[FUNDAMENTAL_TYPE_ID (type)] = (gpointer) table; |
|
112 |
|
113 g_hash_table_insert (gst_value_hash, (gpointer) type, (gpointer) table); |
|
114 } |
|
115 |
86 |
116 /******** |
87 /******** |
117 * list * |
88 * list * |
118 ********/ |
89 ********/ |
119 |
90 |
127 guint i; |
98 guint i; |
128 GArray *array = value->data[0].v_pointer; |
99 GArray *array = value->data[0].v_pointer; |
129 GString *s; |
100 GString *s; |
130 GValue *v; |
101 GValue *v; |
131 gchar *s_val; |
102 gchar *s_val; |
132 guint alen = array->len; |
|
133 |
103 |
134 /* estimate minimum string length to minimise re-allocs in GString */ |
104 /* estimate minimum string length to minimise re-allocs in GString */ |
135 s = g_string_sized_new (2 + (6 * alen) + 2); |
105 s = g_string_sized_new (2 + (6 * array->len) + 2); |
136 g_string_append (s, begin); |
106 g_string_append (s, begin); |
137 for (i = 0; i < alen; i++) { |
107 for (i = 0; i < array->len; i++) { |
138 v = &g_array_index (array, GValue, i); |
108 v = &g_array_index (array, GValue, i); |
139 s_val = gst_value_serialize (v); |
109 s_val = gst_value_serialize (v); |
140 g_string_append (s, s_val); |
110 g_string_append (s, s_val); |
141 g_free (s_val); |
111 g_free (s_val); |
142 if (i < alen - 1) { |
112 if (i < array->len - 1) { |
143 g_string_append_len (s, ", ", 2); |
113 g_string_append_len (s, ", ", 2); |
144 } |
114 } |
145 } |
115 } |
146 g_string_append (s, end); |
116 g_string_append (s, end); |
147 return g_string_free (s, FALSE); |
117 return g_string_free (s, FALSE); |
154 GValue *list_value; |
124 GValue *list_value; |
155 GArray *array; |
125 GArray *array; |
156 GString *s; |
126 GString *s; |
157 guint i; |
127 guint i; |
158 gchar *list_s; |
128 gchar *list_s; |
159 guint alen; |
|
160 |
129 |
161 array = src_value->data[0].v_pointer; |
130 array = src_value->data[0].v_pointer; |
162 alen = array->len; |
|
163 |
131 |
164 /* estimate minimum string length to minimise re-allocs in GString */ |
132 /* estimate minimum string length to minimise re-allocs in GString */ |
165 s = g_string_sized_new (2 + (10 * alen) + 2); |
133 s = g_string_sized_new (2 + (10 * array->len) + 2); |
166 g_string_append (s, begin); |
134 g_string_append (s, begin); |
167 for (i = 0; i < alen; i++) { |
135 for (i = 0; i < array->len; i++) { |
168 list_value = &g_array_index (array, GValue, i); |
136 list_value = &g_array_index (array, GValue, i); |
169 |
137 |
170 if (i != 0) { |
138 if (i != 0) { |
171 g_string_append_len (s, ", ", 2); |
139 g_string_append_len (s, ", ", 2); |
172 } |
140 } |
182 /* |
150 /* |
183 * helper function to see if a type is fixed. Is used internally here and |
151 * helper function to see if a type is fixed. Is used internally here and |
184 * there. Do not export, since it doesn't work for types where the content |
152 * there. Do not export, since it doesn't work for types where the content |
185 * decides the fixedness (e.g. GST_TYPE_ARRAY). |
153 * decides the fixedness (e.g. GST_TYPE_ARRAY). |
186 */ |
154 */ |
|
155 |
187 static gboolean |
156 static gboolean |
188 gst_type_is_fixed (GType type) |
157 gst_type_is_fixed (GType type) |
189 { |
158 { |
190 /* the basic int, string, double types */ |
159 if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE || |
191 if (type <= G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) { |
160 type == GST_TYPE_LIST) { |
|
161 return FALSE; |
|
162 } |
|
163 if (G_TYPE_FUNDAMENTAL (type) <= |
|
164 G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) { |
192 return TRUE; |
165 return TRUE; |
193 } |
166 } |
194 /* our fundamental types that are certainly not fixed */ |
167 if (type == GST_TYPE_BUFFER || type == GST_TYPE_FOURCC |
195 if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE || |
168 || type == GST_TYPE_ARRAY || type == GST_TYPE_FRACTION) { |
196 type == GST_TYPE_LIST || type == GST_TYPE_FRACTION_RANGE) { |
|
197 return FALSE; |
|
198 } |
|
199 /* other (boxed) types that are fixed */ |
|
200 if (type == GST_TYPE_BUFFER) { |
|
201 return TRUE; |
|
202 } |
|
203 /* heavy checks */ |
|
204 if (G_TYPE_IS_FUNDAMENTAL (type) || G_TYPE_FUNDAMENTAL (type) <= |
|
205 G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_GLIB_LAST)) { |
|
206 return TRUE; |
169 return TRUE; |
207 } |
170 } |
208 |
171 |
209 return FALSE; |
172 return FALSE; |
210 } |
173 } |
218 |
181 |
219 static GArray * |
182 static GArray * |
220 copy_garray_of_gstvalue (const GArray * src) |
183 copy_garray_of_gstvalue (const GArray * src) |
221 { |
184 { |
222 GArray *dest; |
185 GArray *dest; |
223 guint i, len; |
186 guint i; |
224 |
187 |
225 len = src->len; |
188 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), src->len); |
226 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), len); |
189 g_array_set_size (dest, src->len); |
227 g_array_set_size (dest, len); |
190 for (i = 0; i < src->len; i++) { |
228 for (i = 0; i < len; i++) { |
|
229 gst_value_init_and_copy (&g_array_index (dest, GValue, i), |
191 gst_value_init_and_copy (&g_array_index (dest, GValue, i), |
230 &g_array_index (src, GValue, i)); |
192 &g_array_index (src, GValue, i)); |
231 } |
193 } |
232 |
194 |
233 return dest; |
195 return dest; |
241 } |
203 } |
242 |
204 |
243 static void |
205 static void |
244 gst_value_free_list_or_array (GValue * value) |
206 gst_value_free_list_or_array (GValue * value) |
245 { |
207 { |
246 guint i, len; |
208 guint i; |
247 GArray *src = (GArray *) value->data[0].v_pointer; |
209 GArray *src = (GArray *) value->data[0].v_pointer; |
248 len = src->len; |
|
249 |
210 |
250 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) { |
211 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) { |
251 for (i = 0; i < len; i++) { |
212 for (i = 0; i < src->len; i++) { |
252 g_value_unset (&g_array_index (src, GValue, i)); |
213 g_value_unset (&g_array_index (src, GValue, i)); |
253 } |
214 } |
254 g_array_free (src, TRUE); |
215 g_array_free (src, TRUE); |
255 } |
216 } |
256 } |
217 } |
597 gst_value_compare_array (const GValue * value1, const GValue * value2) |
558 gst_value_compare_array (const GValue * value1, const GValue * value2) |
598 { |
559 { |
599 guint i; |
560 guint i; |
600 GArray *array1 = value1->data[0].v_pointer; |
561 GArray *array1 = value1->data[0].v_pointer; |
601 GArray *array2 = value2->data[0].v_pointer; |
562 GArray *array2 = value2->data[0].v_pointer; |
602 guint len = array1->len; |
|
603 GValue *v1; |
563 GValue *v1; |
604 GValue *v2; |
564 GValue *v2; |
605 |
565 |
606 if (len != array2->len) |
566 if (array1->len != array2->len) |
607 return GST_VALUE_UNORDERED; |
567 return GST_VALUE_UNORDERED; |
608 |
568 |
609 for (i = 0; i < len; i++) { |
569 for (i = 0; i < array1->len; i++) { |
610 v1 = &g_array_index (array1, GValue, i); |
570 v1 = &g_array_index (array1, GValue, i); |
611 v2 = &g_array_index (array2, GValue, i); |
571 v2 = &g_array_index (array2, GValue, i); |
612 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL) |
572 if (gst_value_compare (v1, v2) != GST_VALUE_EQUAL) |
613 return GST_VALUE_UNORDERED; |
573 return GST_VALUE_UNORDERED; |
614 } |
574 } |
1078 |
1038 |
1079 static void |
1039 static void |
1080 gst_value_init_fraction_range (GValue * value) |
1040 gst_value_init_fraction_range (GValue * value) |
1081 { |
1041 { |
1082 GValue *vals; |
1042 GValue *vals; |
1083 GType ftype; |
1043 |
1084 |
1044 value->data[0].v_pointer = vals = g_new0 (GValue, 2); |
1085 ftype = GST_TYPE_FRACTION; |
1045 g_value_init (&vals[0], GST_TYPE_FRACTION); |
1086 |
1046 g_value_init (&vals[1], GST_TYPE_FRACTION); |
1087 value->data[0].v_pointer = vals = g_slice_alloc0 (2 * sizeof (GValue)); |
|
1088 g_value_init (&vals[0], ftype); |
|
1089 g_value_init (&vals[1], ftype); |
|
1090 } |
1047 } |
1091 |
1048 |
1092 static void |
1049 static void |
1093 gst_value_free_fraction_range (GValue * value) |
1050 gst_value_free_fraction_range (GValue * value) |
1094 { |
1051 { |
1095 GValue *vals = (GValue *) value->data[0].v_pointer; |
1052 GValue *vals = (GValue *) value->data[0].v_pointer; |
1096 |
1053 |
1097 if (vals != NULL) { |
1054 if (vals != NULL) { |
1098 g_value_unset (&vals[0]); |
1055 g_value_unset (&vals[0]); |
1099 g_value_unset (&vals[1]); |
1056 g_value_unset (&vals[1]); |
1100 g_slice_free1 (2 * sizeof (GValue), vals); |
1057 g_free (vals); |
1101 value->data[0].v_pointer = NULL; |
1058 value->data[0].v_pointer = NULL; |
1102 } |
1059 } |
1103 } |
1060 } |
1104 |
1061 |
1105 static void |
1062 static void |
1107 { |
1064 { |
1108 GValue *vals = (GValue *) dest_value->data[0].v_pointer; |
1065 GValue *vals = (GValue *) dest_value->data[0].v_pointer; |
1109 GValue *src_vals = (GValue *) src_value->data[0].v_pointer; |
1066 GValue *src_vals = (GValue *) src_value->data[0].v_pointer; |
1110 |
1067 |
1111 if (vals == NULL) { |
1068 if (vals == NULL) { |
1112 gst_value_init_fraction_range (dest_value); |
1069 dest_value->data[0].v_pointer = vals = g_new0 (GValue, 2); |
1113 vals = dest_value->data[0].v_pointer; |
1070 g_return_if_fail (vals != NULL); |
1114 } |
1071 g_value_init (&vals[0], GST_TYPE_FRACTION); |
|
1072 g_value_init (&vals[1], GST_TYPE_FRACTION); |
|
1073 } |
|
1074 |
1115 if (src_vals != NULL) { |
1075 if (src_vals != NULL) { |
1116 g_value_copy (&src_vals[0], &vals[0]); |
1076 g_value_copy (&src_vals[0], &vals[0]); |
1117 g_value_copy (&src_vals[1], &vals[1]); |
1077 g_value_copy (&src_vals[1], &vals[1]); |
1118 } |
1078 } |
1119 } |
1079 } |
1126 |
1086 |
1127 if (n_collect_values != 4) |
1087 if (n_collect_values != 4) |
1128 return g_strdup_printf ("not enough value locations for `%s' passed", |
1088 return g_strdup_printf ("not enough value locations for `%s' passed", |
1129 G_VALUE_TYPE_NAME (value)); |
1089 G_VALUE_TYPE_NAME (value)); |
1130 if (vals == NULL) { |
1090 if (vals == NULL) { |
1131 gst_value_init_fraction_range (value); |
1091 value->data[0].v_pointer = vals = g_new0 (GValue, 2); |
1132 vals = value->data[0].v_pointer; |
1092 if (vals == NULL) |
|
1093 return g_strdup_printf ("Could not initialise`%s' during collect", |
|
1094 G_VALUE_TYPE_NAME (value)); |
|
1095 g_value_init (&vals[0], GST_TYPE_FRACTION); |
|
1096 g_value_init (&vals[1], GST_TYPE_FRACTION); |
1133 } |
1097 } |
1134 |
1098 |
1135 gst_value_set_fraction (&vals[0], collect_values[0].v_int, |
1099 gst_value_set_fraction (&vals[0], collect_values[0].v_int, |
1136 collect_values[1].v_int); |
1100 collect_values[1].v_int); |
1137 gst_value_set_fraction (&vals[1], collect_values[2].v_int, |
1101 gst_value_set_fraction (&vals[1], collect_values[2].v_int, |
1146 { |
1110 { |
1147 int i; |
1111 int i; |
1148 int *dest_values[4]; |
1112 int *dest_values[4]; |
1149 GValue *vals = (GValue *) value->data[0].v_pointer; |
1113 GValue *vals = (GValue *) value->data[0].v_pointer; |
1150 |
1114 |
1151 if (G_UNLIKELY (n_collect_values != 4)) |
1115 if (n_collect_values != 4) |
1152 return g_strdup_printf ("not enough value locations for `%s' passed", |
1116 return g_strdup_printf ("not enough value locations for `%s' passed", |
1153 G_VALUE_TYPE_NAME (value)); |
1117 G_VALUE_TYPE_NAME (value)); |
1154 |
1118 |
1155 for (i = 0; i < 4; i++) { |
1119 for (i = 0; i < 4; i++) { |
1156 if (G_UNLIKELY (collect_values[i].v_pointer == NULL)) { |
1120 if (collect_values[i].v_pointer == NULL) { |
1157 return g_strdup_printf ("value location for `%s' passed as NULL", |
1121 return g_strdup_printf ("value location for `%s' passed as NULL", |
1158 G_VALUE_TYPE_NAME (value)); |
1122 G_VALUE_TYPE_NAME (value)); |
1159 } |
1123 } |
1160 dest_values[i] = collect_values[i].v_pointer; |
1124 dest_values[i] = collect_values[i].v_pointer; |
1161 } |
1125 } |
1162 |
1126 |
1163 if (G_UNLIKELY (vals == NULL)) { |
1127 if (vals == NULL) { |
1164 return g_strdup_printf ("Uninitialised `%s' passed", |
1128 return g_strdup_printf ("Uninitialised `%s' passed", |
1165 G_VALUE_TYPE_NAME (value)); |
1129 G_VALUE_TYPE_NAME (value)); |
1166 } |
1130 } |
1167 |
1131 |
1168 dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]); |
1132 dest_values[0][0] = gst_value_get_fraction_numerator (&vals[0]); |
1169 dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]); |
1133 dest_values[1][0] = gst_value_get_fraction_denominator (&vals[0]); |
1170 dest_values[2][0] = gst_value_get_fraction_numerator (&vals[1]); |
1134 dest_values[2][0] = gst_value_get_fraction_denominator (&vals[1]); |
1171 dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]); |
1135 dest_values[3][0] = gst_value_get_fraction_denominator (&vals[1]); |
1172 return NULL; |
1136 return NULL; |
1173 } |
1137 } |
1174 |
1138 |
1175 /** |
1139 /** |
1192 |
1156 |
1193 g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value)); |
1157 g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value)); |
1194 |
1158 |
1195 vals = (GValue *) value->data[0].v_pointer; |
1159 vals = (GValue *) value->data[0].v_pointer; |
1196 if (vals == NULL) { |
1160 if (vals == NULL) { |
1197 gst_value_init_fraction_range (value); |
1161 value->data[0].v_pointer = vals = g_new0 (GValue, 2); |
1198 vals = value->data[0].v_pointer; |
1162 g_value_init (&vals[0], GST_TYPE_FRACTION); |
1199 } |
1163 g_value_init (&vals[1], GST_TYPE_FRACTION); |
|
1164 } |
|
1165 |
1200 g_value_copy (start, &vals[0]); |
1166 g_value_copy (start, &vals[0]); |
1201 g_value_copy (end, &vals[1]); |
1167 g_value_copy (end, &vals[1]); |
1202 } |
1168 } |
1203 |
1169 |
1204 /** |
1170 /** |
1466 static char * |
1432 static char * |
1467 gst_value_serialize_structure (const GValue * value) |
1433 gst_value_serialize_structure (const GValue * value) |
1468 { |
1434 { |
1469 GstStructure *structure = g_value_get_boxed (value); |
1435 GstStructure *structure = g_value_get_boxed (value); |
1470 |
1436 |
1471 return gst_string_take_and_wrap (gst_structure_to_string (structure)); |
1437 return gst_structure_to_string (structure); |
1472 } |
1438 } |
1473 |
1439 |
1474 static gboolean |
1440 static gboolean |
1475 gst_value_deserialize_structure (GValue * dest, const gchar * s) |
1441 gst_value_deserialize_structure (GValue * dest, const gchar * s) |
1476 { |
1442 { |
1477 GstStructure *structure; |
1443 GstStructure *structure; |
1478 |
1444 |
1479 if (*s != '"') { |
1445 structure = gst_structure_from_string (s, NULL); |
1480 structure = gst_structure_from_string (s, NULL); |
1446 |
1481 } else { |
1447 if (structure) { |
1482 gchar *str = gst_string_unwrap (s); |
1448 g_value_set_boxed (dest, structure); |
1483 |
|
1484 if (G_UNLIKELY (!str)) |
|
1485 return FALSE; |
|
1486 |
|
1487 structure = gst_structure_from_string (str, NULL); |
|
1488 g_free (str); |
|
1489 } |
|
1490 |
|
1491 if (G_LIKELY (structure)) { |
|
1492 g_value_take_boxed (dest, structure); |
|
1493 return TRUE; |
1449 return TRUE; |
1494 } |
1450 } |
1495 return FALSE; |
1451 return FALSE; |
1496 } |
1452 } |
1497 |
1453 |
1905 **********/ |
1861 **********/ |
1906 |
1862 |
1907 static gint |
1863 static gint |
1908 gst_value_compare_string (const GValue * value1, const GValue * value2) |
1864 gst_value_compare_string (const GValue * value1, const GValue * value2) |
1909 { |
1865 { |
1910 if (G_UNLIKELY (!value1->data[0].v_pointer || !value2->data[0].v_pointer)) { |
1866 int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer); |
1911 /* if only one is NULL, no match - otherwise both NULL == EQUAL */ |
1867 |
1912 if (value1->data[0].v_pointer != value2->data[0].v_pointer) |
1868 if (x < 0) |
1913 return GST_VALUE_UNORDERED; |
1869 return GST_VALUE_LESS_THAN; |
1914 } else { |
1870 if (x > 0) |
1915 int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer); |
1871 return GST_VALUE_GREATER_THAN; |
1916 |
|
1917 if (x < 0) |
|
1918 return GST_VALUE_LESS_THAN; |
|
1919 if (x > 0) |
|
1920 return GST_VALUE_GREATER_THAN; |
|
1921 } |
|
1922 |
|
1923 return GST_VALUE_EQUAL; |
1872 return GST_VALUE_EQUAL; |
1924 } |
1873 } |
1925 |
1874 |
1926 static int |
1875 /* keep in sync with gststructure.c */ |
1927 gst_string_measure_wrapping (const gchar * s) |
1876 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \ |
1928 { |
1877 ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \ |
|
1878 ((c) == '.')) |
|
1879 |
|
1880 static gchar * |
|
1881 gst_string_wrap (const gchar * s) |
|
1882 { |
|
1883 const gchar *t; |
1929 int len; |
1884 int len; |
|
1885 gchar *d, *e; |
1930 gboolean wrap = FALSE; |
1886 gboolean wrap = FALSE; |
1931 |
1887 |
1932 if (G_UNLIKELY (s == NULL)) |
|
1933 return -1; |
|
1934 |
|
1935 /* Special case: the actual string NULL needs wrapping */ |
|
1936 if (G_UNLIKELY (strcmp (s, "NULL") == 0)) |
|
1937 return 4; |
|
1938 |
|
1939 len = 0; |
1888 len = 0; |
1940 while (*s) { |
1889 t = s; |
1941 if (GST_ASCII_IS_STRING (*s)) { |
1890 if (!s) |
|
1891 return NULL; |
|
1892 while (*t) { |
|
1893 if (GST_ASCII_IS_STRING (*t)) { |
1942 len++; |
1894 len++; |
1943 } else if (*s < 0x20 || *s >= 0x7f) { |
1895 } else if (*t < 0x20 || *t >= 0x7f) { |
1944 wrap = TRUE; |
1896 wrap = TRUE; |
1945 len += 4; |
1897 len += 4; |
1946 } else { |
1898 } else { |
1947 wrap = TRUE; |
1899 wrap = TRUE; |
1948 len += 2; |
1900 len += 2; |
1949 } |
1901 } |
1950 s++; |
1902 t++; |
1951 } |
1903 } |
1952 |
1904 |
1953 /* Wrap the string if we found something that needs |
1905 if (!wrap) |
1954 * wrapping, or the empty string (len == 0) */ |
1906 return g_strdup (s); |
1955 return (wrap || len == 0) ? len : -1; |
|
1956 } |
|
1957 |
|
1958 static gchar * |
|
1959 gst_string_wrap_inner (const gchar * s, int len) |
|
1960 { |
|
1961 gchar *d, *e; |
|
1962 |
1907 |
1963 e = d = g_malloc (len + 3); |
1908 e = d = g_malloc (len + 3); |
1964 |
1909 |
1965 *e++ = '\"'; |
1910 *e++ = '\"'; |
1966 while (*s) { |
1911 t = s; |
1967 if (GST_ASCII_IS_STRING (*s)) { |
1912 while (*t) { |
1968 *e++ = *s++; |
1913 if (GST_ASCII_IS_STRING (*t)) { |
1969 } else if (*s < 0x20 || *s >= 0x7f) { |
1914 *e++ = *t++; |
|
1915 } else if (*t < 0x20 || *t >= 0x7f) { |
1970 *e++ = '\\'; |
1916 *e++ = '\\'; |
1971 *e++ = '0' + ((*(guchar *) s) >> 6); |
1917 *e++ = '0' + ((*(guchar *) t) >> 6); |
1972 *e++ = '0' + (((*s) >> 3) & 0x7); |
1918 *e++ = '0' + (((*t) >> 3) & 0x7); |
1973 *e++ = '0' + ((*s++) & 0x7); |
1919 *e++ = '0' + ((*t++) & 0x7); |
1974 } else { |
1920 } else { |
1975 *e++ = '\\'; |
1921 *e++ = '\\'; |
1976 *e++ = *s++; |
1922 *e++ = *t++; |
1977 } |
1923 } |
1978 } |
1924 } |
1979 *e++ = '\"'; |
1925 *e++ = '\"'; |
1980 *e = 0; |
1926 *e = 0; |
1981 |
1927 |
1982 g_assert (e - d <= len + 3); |
|
1983 return d; |
1928 return d; |
1984 } |
|
1985 |
|
1986 /* Do string wrapping/escaping */ |
|
1987 static gchar * |
|
1988 gst_string_wrap (const gchar * s) |
|
1989 { |
|
1990 int len = gst_string_measure_wrapping (s); |
|
1991 |
|
1992 if (G_LIKELY (len < 0)) |
|
1993 return g_strdup (s); |
|
1994 |
|
1995 return gst_string_wrap_inner (s, len); |
|
1996 } |
|
1997 |
|
1998 /* Same as above, but take ownership of the string */ |
|
1999 static gchar * |
|
2000 gst_string_take_and_wrap (gchar * s) |
|
2001 { |
|
2002 gchar *out; |
|
2003 int len = gst_string_measure_wrapping (s); |
|
2004 |
|
2005 if (G_LIKELY (len < 0)) |
|
2006 return s; |
|
2007 |
|
2008 out = gst_string_wrap_inner (s, len); |
|
2009 g_free (s); |
|
2010 |
|
2011 return out; |
|
2012 } |
1929 } |
2013 |
1930 |
2014 /* |
1931 /* |
2015 * This function takes a string delimited with double quotes (") |
1932 * This function takes a string delimited with double quotes (") |
2016 * and unescapes any \xxx octal numbers. |
1933 * and unescapes any \xxx octal numbers. |
2103 } |
2020 } |
2104 |
2021 |
2105 static gboolean |
2022 static gboolean |
2106 gst_value_deserialize_string (GValue * dest, const gchar * s) |
2023 gst_value_deserialize_string (GValue * dest, const gchar * s) |
2107 { |
2024 { |
2108 if (G_UNLIKELY (strcmp (s, "NULL") == 0)) { |
2025 if (*s != '"') { |
2109 g_value_set_string (dest, NULL); |
|
2110 return TRUE; |
|
2111 } else if (G_LIKELY (*s != '"')) { |
|
2112 if (!g_utf8_validate (s, -1, NULL)) |
2026 if (!g_utf8_validate (s, -1, NULL)) |
2113 return FALSE; |
2027 return FALSE; |
2114 g_value_set_string (dest, s); |
2028 g_value_set_string (dest, s); |
2115 return TRUE; |
2029 return TRUE; |
2116 } else { |
2030 } else { |
2117 gchar *str = gst_string_unwrap (s); |
2031 gchar *str = gst_string_unwrap (s); |
2118 if (G_UNLIKELY (!str)) |
2032 |
|
2033 if (!str) |
2119 return FALSE; |
2034 return FALSE; |
2120 g_value_take_string (dest, str); |
2035 g_value_take_string (dest, str); |
2121 } |
2036 } |
2122 |
2037 |
2123 return TRUE; |
2038 return TRUE; |
2776 const GValue * subtrahend) |
2691 const GValue * subtrahend) |
2777 { |
2692 { |
2778 guint i, size; |
2693 guint i, size; |
2779 GValue subtraction = { 0, }; |
2694 GValue subtraction = { 0, }; |
2780 gboolean ret = FALSE; |
2695 gboolean ret = FALSE; |
2781 GType ltype; |
|
2782 |
|
2783 ltype = gst_value_list_get_type (); |
|
2784 |
2696 |
2785 size = gst_value_list_get_size (minuend); |
2697 size = gst_value_list_get_size (minuend); |
2786 for (i = 0; i < size; i++) { |
2698 for (i = 0; i < size; i++) { |
2787 const GValue *cur = gst_value_list_get_value (minuend, i); |
2699 const GValue *cur = gst_value_list_get_value (minuend, i); |
2788 |
2700 |
2789 if (gst_value_subtract (&subtraction, cur, subtrahend)) { |
2701 if (gst_value_subtract (&subtraction, cur, subtrahend)) { |
2790 if (!ret) { |
2702 if (!ret) { |
2791 gst_value_init_and_copy (dest, &subtraction); |
2703 gst_value_init_and_copy (dest, &subtraction); |
2792 ret = TRUE; |
2704 ret = TRUE; |
2793 } else if (G_VALUE_HOLDS (dest, ltype) |
2705 } else if (GST_VALUE_HOLDS_LIST (dest) |
2794 && !G_VALUE_HOLDS (&subtraction, ltype)) { |
2706 && GST_VALUE_HOLDS_LIST (&subtraction)) { |
|
2707 /* unroll */ |
|
2708 GValue unroll = { 0, }; |
|
2709 |
|
2710 gst_value_init_and_copy (&unroll, dest); |
|
2711 g_value_unset (dest); |
|
2712 gst_value_list_concat (dest, &unroll, &subtraction); |
|
2713 } else if (GST_VALUE_HOLDS_LIST (dest)) { |
2795 gst_value_list_append_value (dest, &subtraction); |
2714 gst_value_list_append_value (dest, &subtraction); |
2796 } else { |
2715 } else { |
2797 GValue temp = { 0, }; |
2716 GValue temp = { 0, }; |
2798 |
2717 |
2799 gst_value_init_and_copy (&temp, dest); |
2718 gst_value_init_and_copy (&temp, dest); |
2936 |
2855 |
2937 /************** |
2856 /************** |
2938 * comparison * |
2857 * comparison * |
2939 **************/ |
2858 **************/ |
2940 |
2859 |
|
2860 /** |
|
2861 * gst_value_can_compare: |
|
2862 * @value1: a value to compare |
|
2863 * @value2: another value to compare |
|
2864 * |
|
2865 * Determines if @value1 and @value2 can be compared. |
|
2866 * |
|
2867 * Returns: TRUE if the values can be compared |
|
2868 */ |
|
2869 #ifdef __SYMBIAN32__ |
|
2870 EXPORT_C |
|
2871 #endif |
|
2872 |
|
2873 gboolean |
|
2874 gst_value_can_compare (const GValue * value1, const GValue * value2) |
|
2875 { |
|
2876 GstValueTable *table; |
|
2877 guint i; |
|
2878 |
|
2879 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) |
|
2880 return FALSE; |
|
2881 |
|
2882 for (i = 0; i < gst_value_table->len; i++) { |
|
2883 table = &g_array_index (gst_value_table, GstValueTable, i); |
|
2884 if (g_type_is_a (G_VALUE_TYPE (value1), table->type) && table->compare) |
|
2885 return TRUE; |
|
2886 } |
|
2887 |
|
2888 return FALSE; |
|
2889 } |
|
2890 |
2941 /* |
2891 /* |
2942 * gst_value_get_compare_func: |
2892 * gst_value_get_compare_func: |
2943 * @value1: a value to get the compare function for |
2893 * @value1: a value to get the compare function for |
2944 * |
2894 * |
2945 * Determines the compare function to be used with values of the same type as |
2895 * Determines the compare function to be used with values of the same type as |
2950 static GstValueCompareFunc |
2900 static GstValueCompareFunc |
2951 gst_value_get_compare_func (const GValue * value1) |
2901 gst_value_get_compare_func (const GValue * value1) |
2952 { |
2902 { |
2953 GstValueTable *table, *best = NULL; |
2903 GstValueTable *table, *best = NULL; |
2954 guint i; |
2904 guint i; |
2955 GType type1; |
2905 |
2956 |
2906 for (i = 0; i < gst_value_table->len; i++) { |
2957 type1 = G_VALUE_TYPE (value1); |
2907 table = &g_array_index (gst_value_table, GstValueTable, i); |
2958 |
2908 if (table->type == G_VALUE_TYPE (value1) && table->compare != NULL) { |
2959 /* this is a fast check */ |
2909 best = table; |
2960 best = gst_value_hash_lookup_type (type1); |
2910 break; |
2961 |
|
2962 /* slower checks */ |
|
2963 if (G_UNLIKELY (!best || !best->compare)) { |
|
2964 guint len = gst_value_table->len; |
|
2965 |
|
2966 best = NULL; |
|
2967 for (i = 0; i < len; i++) { |
|
2968 table = &g_array_index (gst_value_table, GstValueTable, i); |
|
2969 if (table->compare && g_type_is_a (type1, table->type)) { |
|
2970 if (!best || g_type_is_a (table->type, best->type)) |
|
2971 best = table; |
|
2972 } |
|
2973 } |
2911 } |
2974 } |
2912 if (g_type_is_a (G_VALUE_TYPE (value1), table->type)) { |
2975 if (G_LIKELY (best)) |
2913 if (!best || g_type_is_a (table->type, best->type)) |
|
2914 best = table; |
|
2915 } |
|
2916 } |
|
2917 if (best) { |
2976 return best->compare; |
2918 return best->compare; |
2977 |
2919 } |
2978 return NULL; |
2920 return NULL; |
2979 } |
|
2980 |
|
2981 /** |
|
2982 * gst_value_can_compare: |
|
2983 * @value1: a value to compare |
|
2984 * @value2: another value to compare |
|
2985 * |
|
2986 * Determines if @value1 and @value2 can be compared. |
|
2987 * |
|
2988 * Returns: TRUE if the values can be compared |
|
2989 */ |
|
2990 #ifdef __SYMBIAN32__ |
|
2991 EXPORT_C |
|
2992 #endif |
|
2993 |
|
2994 gboolean |
|
2995 gst_value_can_compare (const GValue * value1, const GValue * value2) |
|
2996 { |
|
2997 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2)) |
|
2998 return FALSE; |
|
2999 |
|
3000 return gst_value_get_compare_func (value1) != NULL; |
|
3001 } |
2921 } |
3002 |
2922 |
3003 /** |
2923 /** |
3004 * gst_value_compare: |
2924 * gst_value_compare: |
3005 * @value1: a value to compare |
2925 * @value1: a value to compare |
3083 |
3002 |
3084 gboolean |
3003 gboolean |
3085 gst_value_can_union (const GValue * value1, const GValue * value2) |
3004 gst_value_can_union (const GValue * value1, const GValue * value2) |
3086 { |
3005 { |
3087 GstValueUnionInfo *union_info; |
3006 GstValueUnionInfo *union_info; |
3088 guint i, len; |
3007 guint i; |
3089 |
3008 |
3090 len = gst_value_union_funcs->len; |
3009 for (i = 0; i < gst_value_union_funcs->len; i++) { |
3091 |
|
3092 for (i = 0; i < len; i++) { |
|
3093 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i); |
3010 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i); |
3094 if (union_info->type1 == G_VALUE_TYPE (value1) && |
3011 if (union_info->type1 == G_VALUE_TYPE (value1) && |
3095 union_info->type2 == G_VALUE_TYPE (value2)) |
3012 union_info->type2 == G_VALUE_TYPE (value2)) |
3096 return TRUE; |
3013 return TRUE; |
3097 if (union_info->type1 == G_VALUE_TYPE (value2) && |
3014 if (union_info->type1 == G_VALUE_TYPE (value2) && |
3119 |
3036 |
3120 gboolean |
3037 gboolean |
3121 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2) |
3038 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2) |
3122 { |
3039 { |
3123 GstValueUnionInfo *union_info; |
3040 GstValueUnionInfo *union_info; |
3124 guint i, len; |
3041 guint i; |
3125 |
3042 |
3126 len = gst_value_union_funcs->len; |
3043 for (i = 0; i < gst_value_union_funcs->len; i++) { |
3127 |
|
3128 for (i = 0; i < len; i++) { |
|
3129 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i); |
3044 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i); |
3130 if (union_info->type1 == G_VALUE_TYPE (value1) && |
3045 if (union_info->type1 == G_VALUE_TYPE (value1) && |
3131 union_info->type2 == G_VALUE_TYPE (value2)) { |
3046 union_info->type2 == G_VALUE_TYPE (value2)) { |
3132 if (union_info->func (dest, value1, value2)) { |
3047 if (union_info->func (dest, value1, value2)) { |
3133 return TRUE; |
3048 return TRUE; |
3194 |
3109 |
3195 gboolean |
3110 gboolean |
3196 gst_value_can_intersect (const GValue * value1, const GValue * value2) |
3111 gst_value_can_intersect (const GValue * value1, const GValue * value2) |
3197 { |
3112 { |
3198 GstValueIntersectInfo *intersect_info; |
3113 GstValueIntersectInfo *intersect_info; |
3199 guint i, len; |
3114 guint i; |
3200 GType ltype, type1, type2; |
|
3201 |
|
3202 ltype = gst_value_list_get_type (); |
|
3203 |
3115 |
3204 /* special cases */ |
3116 /* special cases */ |
3205 if (G_VALUE_HOLDS (value1, ltype) || G_VALUE_HOLDS (value2, ltype)) |
3117 if (GST_VALUE_HOLDS_LIST (value1) || GST_VALUE_HOLDS_LIST (value2)) |
3206 return TRUE; |
3118 return TRUE; |
3207 |
3119 |
3208 type1 = G_VALUE_TYPE (value1); |
3120 for (i = 0; i < gst_value_intersect_funcs->len; i++) { |
3209 type2 = G_VALUE_TYPE (value2); |
|
3210 |
|
3211 /* practically all GstValue types have a compare function (_can_compare=TRUE) |
|
3212 * GstStructure and GstCaps have npot, but are intersectable */ |
|
3213 if (type1 == type2) |
|
3214 return TRUE; |
|
3215 |
|
3216 /* check registered intersect functions */ |
|
3217 len = gst_value_intersect_funcs->len; |
|
3218 for (i = 0; i < len; i++) { |
|
3219 intersect_info = &g_array_index (gst_value_intersect_funcs, |
3121 intersect_info = &g_array_index (gst_value_intersect_funcs, |
3220 GstValueIntersectInfo, i); |
3122 GstValueIntersectInfo, i); |
3221 if ((intersect_info->type1 == type1 && intersect_info->type2 == type2) || |
3123 if (intersect_info->type1 == G_VALUE_TYPE (value1) && |
3222 (intersect_info->type1 == type2 && intersect_info->type2 == type1)) |
3124 intersect_info->type2 == G_VALUE_TYPE (value2)) |
3223 return TRUE; |
3125 if (intersect_info->type2 == G_VALUE_TYPE (value1) && |
|
3126 intersect_info->type1 == G_VALUE_TYPE (value2)) |
|
3127 return TRUE; |
3224 } |
3128 } |
3225 |
3129 |
3226 return gst_value_can_compare (value1, value2); |
3130 return gst_value_can_compare (value1, value2); |
3227 } |
3131 } |
3228 |
3132 |
3247 gboolean |
3151 gboolean |
3248 gst_value_intersect (GValue * dest, const GValue * value1, |
3152 gst_value_intersect (GValue * dest, const GValue * value1, |
3249 const GValue * value2) |
3153 const GValue * value2) |
3250 { |
3154 { |
3251 GstValueIntersectInfo *intersect_info; |
3155 GstValueIntersectInfo *intersect_info; |
3252 guint i, len; |
3156 guint i; |
3253 GType ltype, type1, type2; |
3157 gboolean ret = FALSE; |
3254 |
|
3255 ltype = gst_value_list_get_type (); |
|
3256 |
3158 |
3257 /* special cases first */ |
3159 /* special cases first */ |
3258 if (G_VALUE_HOLDS (value1, ltype)) |
3160 if (GST_VALUE_HOLDS_LIST (value1)) |
3259 return gst_value_intersect_list (dest, value1, value2); |
3161 return gst_value_intersect_list (dest, value1, value2); |
3260 if (G_VALUE_HOLDS (value2, ltype)) |
3162 if (GST_VALUE_HOLDS_LIST (value2)) |
3261 return gst_value_intersect_list (dest, value2, value1); |
3163 return gst_value_intersect_list (dest, value2, value1); |
|
3164 |
|
3165 for (i = 0; i < gst_value_intersect_funcs->len; i++) { |
|
3166 intersect_info = &g_array_index (gst_value_intersect_funcs, |
|
3167 GstValueIntersectInfo, i); |
|
3168 if (intersect_info->type1 == G_VALUE_TYPE (value1) && |
|
3169 intersect_info->type2 == G_VALUE_TYPE (value2)) { |
|
3170 ret = intersect_info->func (dest, value1, value2); |
|
3171 return ret; |
|
3172 } |
|
3173 if (intersect_info->type1 == G_VALUE_TYPE (value2) && |
|
3174 intersect_info->type2 == G_VALUE_TYPE (value1)) { |
|
3175 ret = intersect_info->func (dest, value2, value1); |
|
3176 return ret; |
|
3177 } |
|
3178 } |
3262 |
3179 |
3263 if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) { |
3180 if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) { |
3264 gst_value_init_and_copy (dest, value1); |
3181 gst_value_init_and_copy (dest, value1); |
3265 return TRUE; |
3182 ret = TRUE; |
3266 } |
3183 } |
3267 |
3184 |
3268 type1 = G_VALUE_TYPE (value1); |
3185 return ret; |
3269 type2 = G_VALUE_TYPE (value2); |
|
3270 |
|
3271 len = gst_value_intersect_funcs->len; |
|
3272 for (i = 0; i < len; i++) { |
|
3273 intersect_info = &g_array_index (gst_value_intersect_funcs, |
|
3274 GstValueIntersectInfo, i); |
|
3275 if (intersect_info->type1 == type1 && intersect_info->type2 == type2) { |
|
3276 return intersect_info->func (dest, value1, value2); |
|
3277 } |
|
3278 if (intersect_info->type1 == type2 && intersect_info->type2 == type1) { |
|
3279 return intersect_info->func (dest, value2, value1); |
|
3280 } |
|
3281 } |
|
3282 return FALSE; |
|
3283 } |
3186 } |
3284 |
3187 |
3285 /** |
3188 /** |
3286 * gst_value_register_intersect_func: |
3189 * gst_value_register_intersect_func: |
3287 * @type1: the first type to intersect |
3190 * @type1: the first type to intersect |
3334 gboolean |
3237 gboolean |
3335 gst_value_subtract (GValue * dest, const GValue * minuend, |
3238 gst_value_subtract (GValue * dest, const GValue * minuend, |
3336 const GValue * subtrahend) |
3239 const GValue * subtrahend) |
3337 { |
3240 { |
3338 GstValueSubtractInfo *info; |
3241 GstValueSubtractInfo *info; |
3339 guint i, len; |
3242 guint i; |
3340 GType ltype, mtype, stype; |
|
3341 |
|
3342 ltype = gst_value_list_get_type (); |
|
3343 |
3243 |
3344 /* special cases first */ |
3244 /* special cases first */ |
3345 if (G_VALUE_HOLDS (minuend, ltype)) |
3245 if (GST_VALUE_HOLDS_LIST (minuend)) |
3346 return gst_value_subtract_from_list (dest, minuend, subtrahend); |
3246 return gst_value_subtract_from_list (dest, minuend, subtrahend); |
3347 if (G_VALUE_HOLDS (subtrahend, ltype)) |
3247 if (GST_VALUE_HOLDS_LIST (subtrahend)) |
3348 return gst_value_subtract_list (dest, minuend, subtrahend); |
3248 return gst_value_subtract_list (dest, minuend, subtrahend); |
3349 |
3249 |
3350 mtype = G_VALUE_TYPE (minuend); |
3250 for (i = 0; i < gst_value_subtract_funcs->len; i++) { |
3351 stype = G_VALUE_TYPE (subtrahend); |
|
3352 |
|
3353 len = gst_value_subtract_funcs->len; |
|
3354 for (i = 0; i < len; i++) { |
|
3355 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i); |
3251 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i); |
3356 if (info->minuend == mtype && info->subtrahend == stype) { |
3252 if (info->minuend == G_VALUE_TYPE (minuend) && |
|
3253 info->subtrahend == G_VALUE_TYPE (subtrahend)) { |
3357 return info->func (dest, minuend, subtrahend); |
3254 return info->func (dest, minuend, subtrahend); |
3358 } |
3255 } |
3359 } |
3256 } |
3360 |
3257 |
3361 if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) { |
3258 if (gst_value_compare (minuend, subtrahend) != GST_VALUE_EQUAL) { |
3395 |
3292 |
3396 gboolean |
3293 gboolean |
3397 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend) |
3294 gst_value_can_subtract (const GValue * minuend, const GValue * subtrahend) |
3398 { |
3295 { |
3399 GstValueSubtractInfo *info; |
3296 GstValueSubtractInfo *info; |
3400 guint i, len; |
3297 guint i; |
3401 GType ltype, mtype, stype; |
|
3402 |
|
3403 ltype = gst_value_list_get_type (); |
|
3404 |
3298 |
3405 /* special cases */ |
3299 /* special cases */ |
3406 if (G_VALUE_HOLDS (minuend, ltype) || G_VALUE_HOLDS (subtrahend, ltype)) |
3300 if (GST_VALUE_HOLDS_LIST (minuend) || GST_VALUE_HOLDS_LIST (subtrahend)) |
3407 return TRUE; |
3301 return TRUE; |
3408 |
3302 |
3409 mtype = G_VALUE_TYPE (minuend); |
3303 for (i = 0; i < gst_value_subtract_funcs->len; i++) { |
3410 stype = G_VALUE_TYPE (subtrahend); |
|
3411 |
|
3412 len = gst_value_subtract_funcs->len; |
|
3413 for (i = 0; i < len; i++) { |
|
3414 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i); |
3304 info = &g_array_index (gst_value_subtract_funcs, GstValueSubtractInfo, i); |
3415 if (info->minuend == mtype && info->subtrahend == stype) |
3305 if (info->minuend == G_VALUE_TYPE (minuend) && |
|
3306 info->subtrahend == G_VALUE_TYPE (subtrahend)) |
3416 return TRUE; |
3307 return TRUE; |
3417 } |
3308 } |
3418 |
3309 |
3419 return gst_value_can_compare (minuend, subtrahend); |
3310 return gst_value_can_compare (minuend, subtrahend); |
3420 } |
3311 } |
3456 /** |
3347 /** |
3457 * gst_value_register: |
3348 * gst_value_register: |
3458 * @table: structure containing functions to register |
3349 * @table: structure containing functions to register |
3459 * |
3350 * |
3460 * Registers functions to perform calculations on #GValues of a given |
3351 * Registers functions to perform calculations on #GValues of a given |
3461 * type. Each type can only be added once. |
3352 * type. |
3462 */ |
3353 */ |
3463 #ifdef __SYMBIAN32__ |
3354 #ifdef __SYMBIAN32__ |
3464 EXPORT_C |
3355 EXPORT_C |
3465 #endif |
3356 #endif |
3466 |
3357 |
3467 void |
3358 void |
3468 gst_value_register (const GstValueTable * table) |
3359 gst_value_register (const GstValueTable * table) |
3469 { |
3360 { |
3470 GstValueTable *found; |
|
3471 |
|
3472 g_array_append_val (gst_value_table, *table); |
3361 g_array_append_val (gst_value_table, *table); |
3473 |
|
3474 found = gst_value_hash_lookup_type (table->type); |
|
3475 if (found) |
|
3476 g_warning ("adding type %s multiple times", g_type_name (table->type)); |
|
3477 |
|
3478 /* FIXME: we're not really doing the const justice, we assume the table is |
|
3479 * static */ |
|
3480 gst_value_hash_add_type (table->type, table); |
|
3481 } |
3362 } |
3482 |
3363 |
3483 /** |
3364 /** |
3484 * gst_value_init_and_copy: |
3365 * gst_value_init_and_copy: |
3485 * @dest: the target value |
3366 * @dest: the target value |
3513 #endif |
3394 #endif |
3514 |
3395 |
3515 gchar * |
3396 gchar * |
3516 gst_value_serialize (const GValue * value) |
3397 gst_value_serialize (const GValue * value) |
3517 { |
3398 { |
3518 guint i, len; |
3399 guint i; |
3519 GValue s_val = { 0 }; |
3400 GValue s_val = { 0 }; |
3520 GstValueTable *table, *best; |
3401 GstValueTable *table, *best = NULL; |
3521 char *s; |
3402 char *s; |
3522 GType type; |
|
3523 |
3403 |
3524 g_return_val_if_fail (G_IS_VALUE (value), NULL); |
3404 g_return_val_if_fail (G_IS_VALUE (value), NULL); |
3525 |
3405 |
3526 type = G_VALUE_TYPE (value); |
3406 for (i = 0; i < gst_value_table->len; i++) { |
3527 |
3407 table = &g_array_index (gst_value_table, GstValueTable, i); |
3528 best = gst_value_hash_lookup_type (type); |
3408 if (table->serialize == NULL) |
3529 |
3409 continue; |
3530 if (G_UNLIKELY (!best || !best->serialize)) { |
3410 if (table->type == G_VALUE_TYPE (value)) { |
3531 len = gst_value_table->len; |
3411 best = table; |
3532 best = NULL; |
3412 break; |
3533 for (i = 0; i < len; i++) { |
|
3534 table = &g_array_index (gst_value_table, GstValueTable, i); |
|
3535 if (table->serialize && g_type_is_a (type, table->type)) { |
|
3536 if (!best || g_type_is_a (table->type, best->type)) |
|
3537 best = table; |
|
3538 } |
|
3539 } |
3413 } |
3540 } |
3414 if (g_type_is_a (G_VALUE_TYPE (value), table->type)) { |
3541 if (G_LIKELY (best)) |
3415 if (!best || g_type_is_a (table->type, best->type)) |
|
3416 best = table; |
|
3417 } |
|
3418 } |
|
3419 if (best) |
3542 return best->serialize (value); |
3420 return best->serialize (value); |
3543 |
3421 |
3544 g_value_init (&s_val, G_TYPE_STRING); |
3422 g_value_init (&s_val, G_TYPE_STRING); |
3545 if (g_value_transform (value, &s_val)) { |
3423 if (g_value_transform (value, &s_val)) { |
3546 s = gst_string_wrap (g_value_get_string (&s_val)); |
3424 s = gst_string_wrap (g_value_get_string (&s_val)); |
3567 #endif |
3445 #endif |
3568 |
3446 |
3569 gboolean |
3447 gboolean |
3570 gst_value_deserialize (GValue * dest, const gchar * src) |
3448 gst_value_deserialize (GValue * dest, const gchar * src) |
3571 { |
3449 { |
3572 GstValueTable *table, *best; |
3450 GstValueTable *table, *best = NULL; |
3573 guint i, len; |
3451 guint i; |
3574 GType type; |
|
3575 |
3452 |
3576 g_return_val_if_fail (src != NULL, FALSE); |
3453 g_return_val_if_fail (src != NULL, FALSE); |
3577 g_return_val_if_fail (G_IS_VALUE (dest), FALSE); |
3454 g_return_val_if_fail (G_IS_VALUE (dest), FALSE); |
3578 |
3455 |
3579 type = G_VALUE_TYPE (dest); |
3456 for (i = 0; i < gst_value_table->len; i++) { |
3580 |
3457 table = &g_array_index (gst_value_table, GstValueTable, i); |
3581 best = gst_value_hash_lookup_type (type); |
3458 if (table->serialize == NULL) |
3582 if (G_UNLIKELY (!best || !best->deserialize)) { |
3459 continue; |
3583 len = gst_value_table->len; |
3460 |
3584 best = NULL; |
3461 if (table->type == G_VALUE_TYPE (dest)) { |
3585 for (i = 0; i < len; i++) { |
3462 best = table; |
3586 table = &g_array_index (gst_value_table, GstValueTable, i); |
3463 break; |
3587 if (table->deserialize && g_type_is_a (type, table->type)) { |
|
3588 if (!best || g_type_is_a (table->type, best->type)) |
|
3589 best = table; |
|
3590 } |
|
3591 } |
3464 } |
3592 } |
3465 |
3593 if (G_LIKELY (best)) |
3466 if (g_type_is_a (G_VALUE_TYPE (dest), table->type)) { |
|
3467 if (!best || g_type_is_a (table->type, best->type)) |
|
3468 best = table; |
|
3469 } |
|
3470 } |
|
3471 if (best) { |
3594 return best->deserialize (dest, src); |
3472 return best->deserialize (dest, src); |
|
3473 } |
3595 |
3474 |
3596 return FALSE; |
3475 return FALSE; |
3597 } |
3476 } |
3598 |
3477 |
3599 /** |
3478 /** |
4371 |
4240 |
4372 void |
4241 void |
4373 _gst_value_initialize (void) |
4242 _gst_value_initialize (void) |
4374 { |
4243 { |
4375 gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable)); |
4244 gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable)); |
4376 gst_value_hash = g_hash_table_new (NULL, NULL); |
|
4377 gst_value_union_funcs = g_array_new (FALSE, FALSE, |
4245 gst_value_union_funcs = g_array_new (FALSE, FALSE, |
4378 sizeof (GstValueUnionInfo)); |
4246 sizeof (GstValueUnionInfo)); |
4379 gst_value_intersect_funcs = g_array_new (FALSE, FALSE, |
4247 gst_value_intersect_funcs = g_array_new (FALSE, FALSE, |
4380 sizeof (GstValueIntersectInfo)); |
4248 sizeof (GstValueIntersectInfo)); |
4381 gst_value_subtract_funcs = g_array_new (FALSE, FALSE, |
4249 gst_value_subtract_funcs = g_array_new (FALSE, FALSE, |