2 * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
27 #include <gobject/gvaluecollector.h>
30 typedef struct _GstValueUnionInfo GstValueUnionInfo;
31 struct _GstValueUnionInfo
35 GstValueUnionFunc func;
38 typedef struct _GstValueIntersectInfo GstValueIntersectInfo;
39 struct _GstValueIntersectInfo
43 GstValueIntersectFunc func;
46 GType gst_type_fourcc;
47 GType gst_type_int_range;
48 GType gst_type_double_range;
51 static GArray *gst_value_table;
52 static GArray *gst_value_union_funcs;
53 static GArray *gst_value_intersect_funcs;
55 /*************************************/
59 gst_value_init_list (GValue * value)
61 value->data[0].v_pointer = g_array_new (FALSE, TRUE, sizeof (GValue));
65 gst_value_list_array_copy (const GArray * src)
70 dest = g_array_sized_new (FALSE, TRUE, sizeof (GValue), src->len);
71 g_array_set_size (dest, src->len);
72 for (i = 0; i < src->len; i++) {
73 gst_value_init_and_copy (&g_array_index (dest, GValue, i),
74 &g_array_index (src, GValue, i));
81 gst_value_copy_list (const GValue * src_value, GValue * dest_value)
83 dest_value->data[0].v_pointer =
84 gst_value_list_array_copy ((GArray *) src_value->data[0].v_pointer);
88 gst_value_free_list (GValue * value)
91 GArray *src = (GArray *) value->data[0].v_pointer;
93 if ((value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS) == 0) {
94 for (i = 0; i < src->len; i++) {
95 g_value_unset (&g_array_index (src, GValue, i));
97 g_array_free (src, TRUE);
102 gst_value_list_peek_pointer (const GValue * value)
104 return value->data[0].v_pointer;
108 gst_value_collect_list (GValue * value, guint n_collect_values,
109 GTypeCValue * collect_values, guint collect_flags)
111 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
112 value->data[0].v_pointer = collect_values[0].v_pointer;
113 value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
115 value->data[0].v_pointer =
116 gst_value_list_array_copy ((GArray *) collect_values[0].v_pointer);
122 gst_value_lcopy_list (const GValue * value, guint n_collect_values,
123 GTypeCValue * collect_values, guint collect_flags)
125 GArray **dest = collect_values[0].v_pointer;
128 return g_strdup_printf ("value location for `%s' passed as NULL",
129 G_VALUE_TYPE_NAME (value));
130 if (!value->data[0].v_pointer)
131 return g_strdup_printf ("invalid value given for `%s'",
132 G_VALUE_TYPE_NAME (value));
133 if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
134 *dest = (GArray *) value->data[0].v_pointer;
136 *dest = gst_value_list_array_copy ((GArray *) value->data[0].v_pointer);
142 * gst_value_list_prepend_value:
143 * @value: a GstValueList to prepend a value to
144 * @prepend_value: the value to prepend
146 * Prepends @prepend_value to the GstValueList in @value.
150 gst_value_list_prepend_value (GValue * value, const GValue * prepend_value)
152 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
154 g_array_prepend_vals ((GArray *) value->data[0].v_pointer, prepend_value, 1);
158 * gst_value_list_append_value:
159 * @value: a GstValueList to append a value to
160 * @append_value: the value to append
162 * Appends @append_value to the GstValueList in @value.
165 gst_value_list_append_value (GValue * value, const GValue * append_value)
167 g_return_if_fail (GST_VALUE_HOLDS_LIST (value));
169 g_array_append_vals ((GArray *) value->data[0].v_pointer, append_value, 1);
173 * gst_value_list_get_size:
174 * @value: a GstValueList
176 * Gets the number of values contained in @value.
178 * Returns: the number of values
181 gst_value_list_get_size (const GValue * value)
183 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), 0);
185 return ((GArray *) value->data[0].v_pointer)->len;
189 * gst_value_list_get_value:
190 * @value: a GstValueList
193 * Gets the value that is a member of the list contained in @value and
194 * has the index @index.
196 * Returns: the value at the given index
199 gst_value_list_get_value (const GValue * value, guint index)
201 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value), NULL);
202 g_return_val_if_fail (index < gst_value_list_get_size (value), NULL);
204 return (const GValue *) &g_array_index ((GArray *) value->data[0].v_pointer,
209 * gst_value_list_concat:
210 * @dest: an uninitialized #GValue to take the result
211 * @value1: first value to put into the union
212 * @value2: second value to put into the union
214 * Concatenates copies of value1 and value2 into a list. The value
215 * @dest is initialized to the type GST_TYPE_LIST.
218 gst_value_list_concat (GValue * dest, const GValue * value1,
219 const GValue * value2)
221 guint i, value1_length, value2_length;
224 g_return_if_fail (dest != NULL);
225 g_return_if_fail (G_VALUE_TYPE (dest) == 0);
226 g_return_if_fail (G_IS_VALUE (value1));
227 g_return_if_fail (G_IS_VALUE (value2));
230 (GST_VALUE_HOLDS_LIST (value1) ? gst_value_list_get_size (value1) : 1);
232 (GST_VALUE_HOLDS_LIST (value2) ? gst_value_list_get_size (value2) : 1);
233 g_value_init (dest, GST_TYPE_LIST);
234 array = (GArray *) dest->data[0].v_pointer;
235 g_array_set_size (array, value1_length + value2_length);
237 if (GST_VALUE_HOLDS_LIST (value1)) {
238 for (i = 0; i < value1_length; i++) {
239 gst_value_init_and_copy (&g_array_index (array, GValue, i),
240 gst_value_list_get_value (value1, i));
243 gst_value_init_and_copy (&g_array_index (array, GValue, 0), value1);
246 if (GST_VALUE_HOLDS_LIST (value2)) {
247 for (i = 0; i < value2_length; i++) {
248 gst_value_init_and_copy (&g_array_index (array, GValue,
249 i + value1_length), gst_value_list_get_value (value2, i));
252 gst_value_init_and_copy (&g_array_index (array, GValue, value1_length),
258 gst_value_transform_list_string (const GValue * src_value, GValue * dest_value)
266 array = src_value->data[0].v_pointer;
268 s = g_string_new ("{ ");
269 for (i = 0; i < array->len; i++) {
270 list_value = &g_array_index (array, GValue, i);
273 g_string_append (s, ", ");
275 list_s = g_strdup_value_contents (list_value);
276 g_string_append (s, list_s);
279 g_string_append (s, " }");
281 dest_value->data[0].v_pointer = g_string_free (s, FALSE);
285 gst_value_compare_list (const GValue * value1, const GValue * value2)
288 GArray *array1 = value1->data[0].v_pointer;
289 GArray *array2 = value2->data[0].v_pointer;
293 if (array1->len != array2->len)
294 return GST_VALUE_UNORDERED;
296 for (i = 0; i < array1->len; i++) {
297 v1 = &g_array_index (array1, GValue, i);
298 for (j = 0; j < array1->len; j++) {
299 v2 = &g_array_index (array2, GValue, j);
300 if (gst_value_compare (v1, v2) == GST_VALUE_EQUAL)
303 if (j == array1->len) {
304 return GST_VALUE_UNORDERED;
308 return GST_VALUE_EQUAL;
312 gst_value_serialize_list (const GValue * value)
315 GArray *array = value->data[0].v_pointer;
320 s = g_string_new ("{ ");
321 for (i = 0; i < array->len; i++) {
322 v = &g_array_index (array, GValue, i);
323 s_val = gst_value_serialize (v);
324 g_string_append (s, s_val);
326 if (i < array->len - 1) {
327 g_string_append (s, ", ");
330 g_string_append (s, " }");
331 return g_string_free (s, FALSE);
335 gst_value_deserialize_list (GValue * dest, const char *s)
337 g_warning ("unimplemented");
341 /*************************************/
345 gst_value_init_fourcc (GValue * value)
347 value->data[0].v_int = 0;
351 gst_value_copy_fourcc (const GValue * src_value, GValue * dest_value)
353 dest_value->data[0].v_int = src_value->data[0].v_int;
357 gst_value_collect_fourcc (GValue * value, guint n_collect_values,
358 GTypeCValue * collect_values, guint collect_flags)
360 value->data[0].v_int = collect_values[0].v_int;
366 gst_value_lcopy_fourcc (const GValue * value, guint n_collect_values,
367 GTypeCValue * collect_values, guint collect_flags)
369 guint32 *fourcc_p = collect_values[0].v_pointer;
372 return g_strdup_printf ("value location for `%s' passed as NULL",
373 G_VALUE_TYPE_NAME (value));
375 *fourcc_p = value->data[0].v_int;
381 * gst_value_set_fourcc:
382 * @value: a GValue initialized to GST_TYPE_FOURCC
383 * @fourcc: the fourcc to set
385 * Sets @value to @fourcc.
388 gst_value_set_fourcc (GValue * value, guint32 fourcc)
390 g_return_if_fail (GST_VALUE_HOLDS_FOURCC (value));
392 value->data[0].v_int = fourcc;
396 * gst_value_get_fourcc:
397 * @value: a GValue initialized to GST_TYPE_FOURCC
399 * Gets the fourcc contained in @value.
401 * Returns: the fourcc contained in @value.
404 gst_value_get_fourcc (const GValue * value)
406 g_return_val_if_fail (GST_VALUE_HOLDS_FOURCC (value), 0);
408 return value->data[0].v_int;
412 gst_value_transform_fourcc_string (const GValue * src_value,
415 guint32 fourcc = src_value->data[0].v_int;
417 if (g_ascii_isprint ((fourcc >> 0) & 0xff) &&
418 g_ascii_isprint ((fourcc >> 8) & 0xff) &&
419 g_ascii_isprint ((fourcc >> 16) & 0xff) &&
420 g_ascii_isprint ((fourcc >> 24) & 0xff)) {
421 dest_value->data[0].v_pointer =
422 g_strdup_printf (GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
424 dest_value->data[0].v_pointer = g_strdup_printf ("0x%08x", fourcc);
429 gst_value_compare_fourcc (const GValue * value1, const GValue * value2)
431 if (value2->data[0].v_int == value1->data[0].v_int)
432 return GST_VALUE_EQUAL;
433 return GST_VALUE_UNORDERED;
437 gst_value_serialize_fourcc (const GValue * value)
439 guint32 fourcc = value->data[0].v_int;
441 if (g_ascii_isalnum ((fourcc >> 0) & 0xff) &&
442 g_ascii_isalnum ((fourcc >> 8) & 0xff) &&
443 g_ascii_isalnum ((fourcc >> 16) & 0xff) &&
444 g_ascii_isalnum ((fourcc >> 24) & 0xff)) {
445 return g_strdup_printf (GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
447 return g_strdup_printf ("0x%08x", fourcc);
452 gst_value_deserialize_fourcc (GValue * dest, const char *s)
454 gboolean ret = FALSE;
458 if (strlen (s) == 4) {
459 fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]);
461 } else if (g_ascii_isdigit (*s)) {
462 fourcc = strtoul (s, &end, 0);
467 gst_value_set_fourcc (dest, fourcc);
472 /*************************************/
476 gst_value_init_int_range (GValue * value)
478 value->data[0].v_int = 0;
479 value->data[1].v_int = 0;
483 gst_value_copy_int_range (const GValue * src_value, GValue * dest_value)
485 dest_value->data[0].v_int = src_value->data[0].v_int;
486 dest_value->data[1].v_int = src_value->data[1].v_int;
490 gst_value_collect_int_range (GValue * value, guint n_collect_values,
491 GTypeCValue * collect_values, guint collect_flags)
494 value->data[0].v_int = collect_values[0].v_int;
495 value->data[1].v_int = collect_values[1].v_int;
501 gst_value_lcopy_int_range (const GValue * value, guint n_collect_values,
502 GTypeCValue * collect_values, guint collect_flags)
504 guint32 *int_range_start = collect_values[0].v_pointer;
505 guint32 *int_range_end = collect_values[1].v_pointer;
507 if (!int_range_start)
508 return g_strdup_printf ("start value location for `%s' passed as NULL",
509 G_VALUE_TYPE_NAME (value));
511 return g_strdup_printf ("end value location for `%s' passed as NULL",
512 G_VALUE_TYPE_NAME (value));
514 *int_range_start = value->data[0].v_int;
515 *int_range_end = value->data[1].v_int;
521 * gst_value_set_int_range:
522 * @value: a GValue initialized to GST_TYPE_INT_RANGE
523 * @start: the start of the range
524 * @end: the end of the range
526 * Sets @value to the range specified by @start and @end.
529 gst_value_set_int_range (GValue * value, int start, int end)
531 g_return_if_fail (GST_VALUE_HOLDS_INT_RANGE (value));
533 value->data[0].v_int = start;
534 value->data[1].v_int = end;
538 * gst_value_get_int_range_min:
539 * @value: a GValue initialized to GST_TYPE_INT_RANGE
541 * Gets the minimum of the range specified by @value.
543 * Returns: the minumum of the range
546 gst_value_get_int_range_min (const GValue * value)
548 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
550 return value->data[0].v_int;
554 * gst_value_get_int_range_max:
555 * @value: a GValue initialized to GST_TYPE_INT_RANGE
557 * Gets the maximum of the range specified by @value.
559 * Returns: the maxumum of the range
562 gst_value_get_int_range_max (const GValue * value)
564 g_return_val_if_fail (GST_VALUE_HOLDS_INT_RANGE (value), 0);
566 return value->data[1].v_int;
570 gst_value_transform_int_range_string (const GValue * src_value,
573 dest_value->data[0].v_pointer = g_strdup_printf ("[%d,%d]",
574 (int) src_value->data[0].v_int, (int) src_value->data[1].v_int);
578 gst_value_compare_int_range (const GValue * value1, const GValue * value2)
580 if (value2->data[0].v_int == value1->data[0].v_int &&
581 value2->data[0].v_int == value1->data[0].v_int)
582 return GST_VALUE_EQUAL;
583 return GST_VALUE_UNORDERED;
587 gst_value_serialize_int_range (const GValue * value)
589 return g_strdup_printf ("[ %d, %d ]", value->data[0].v_int,
590 value->data[1].v_int);
594 gst_value_deserialize_int_range (GValue * dest, const char *s)
596 g_warning ("unimplemented");
600 /*************************************/
604 gst_value_init_double_range (GValue * value)
606 value->data[0].v_double = 0;
607 value->data[1].v_double = 0;
611 gst_value_copy_double_range (const GValue * src_value, GValue * dest_value)
613 dest_value->data[0].v_double = src_value->data[0].v_double;
614 dest_value->data[1].v_double = src_value->data[1].v_double;
618 gst_value_collect_double_range (GValue * value, guint n_collect_values,
619 GTypeCValue * collect_values, guint collect_flags)
621 value->data[0].v_double = collect_values[0].v_double;
622 value->data[1].v_double = collect_values[1].v_double;
628 gst_value_lcopy_double_range (const GValue * value, guint n_collect_values,
629 GTypeCValue * collect_values, guint collect_flags)
631 gdouble *double_range_start = collect_values[0].v_pointer;
632 gdouble *double_range_end = collect_values[1].v_pointer;
634 if (!double_range_start)
635 return g_strdup_printf ("start value location for `%s' passed as NULL",
636 G_VALUE_TYPE_NAME (value));
637 if (!double_range_end)
638 return g_strdup_printf ("end value location for `%s' passed as NULL",
639 G_VALUE_TYPE_NAME (value));
641 *double_range_start = value->data[0].v_double;
642 *double_range_end = value->data[1].v_double;
648 * gst_value_set_double_range:
649 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
650 * @start: the start of the range
651 * @end: the end of the range
653 * Sets @value to the range specified by @start and @end.
656 gst_value_set_double_range (GValue * value, double start, double end)
658 g_return_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value));
660 value->data[0].v_double = start;
661 value->data[1].v_double = end;
665 * gst_value_get_double_range_min:
666 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
668 * Gets the minimum of the range specified by @value.
670 * Returns: the minumum of the range
673 gst_value_get_double_range_min (const GValue * value)
675 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
677 return value->data[0].v_double;
681 * gst_value_get_double_range_max:
682 * @value: a GValue initialized to GST_TYPE_DOUBLE_RANGE
684 * Gets the maximum of the range specified by @value.
686 * Returns: the maxumum of the range
689 gst_value_get_double_range_max (const GValue * value)
691 g_return_val_if_fail (GST_VALUE_HOLDS_DOUBLE_RANGE (value), 0);
693 return value->data[1].v_double;
697 gst_value_transform_double_range_string (const GValue * src_value,
700 char s1[G_ASCII_DTOSTR_BUF_SIZE], s2[G_ASCII_DTOSTR_BUF_SIZE];
702 dest_value->data[0].v_pointer = g_strdup_printf ("[%s,%s]",
703 g_ascii_dtostr (s1, G_ASCII_DTOSTR_BUF_SIZE,
704 src_value->data[0].v_double),
705 g_ascii_dtostr (s2, G_ASCII_DTOSTR_BUF_SIZE,
706 src_value->data[1].v_double));
710 gst_value_compare_double_range (const GValue * value1, const GValue * value2)
712 if (value2->data[0].v_double == value1->data[0].v_double &&
713 value2->data[0].v_double == value1->data[0].v_double)
714 return GST_VALUE_EQUAL;
715 return GST_VALUE_UNORDERED;
719 gst_value_serialize_double_range (const GValue * value)
721 char d1[G_ASCII_DTOSTR_BUF_SIZE];
722 char d2[G_ASCII_DTOSTR_BUF_SIZE];
724 g_ascii_dtostr (d1, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
725 g_ascii_dtostr (d2, G_ASCII_DTOSTR_BUF_SIZE, value->data[1].v_double);
726 return g_strdup_printf ("[ %s, %s ]", d1, d2);
730 gst_value_deserialize_double_range (GValue * dest, const char *s)
732 g_warning ("unimplemented");
736 /*************************************/
740 * gst_value_set_caps:
741 * @value: a GValue initialized to GST_TYPE_CAPS
742 * @caps: the caps to set the value to
744 * Sets the contents of @value to coorespond to @caps. The actual
745 * #GstCaps structure is copied before it is used.
748 gst_value_set_caps (GValue * value, const GstCaps * caps)
750 g_return_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS);
752 g_value_set_boxed (value, caps);
756 * gst_value_get_caps:
757 * @value: a GValue initialized to GST_TYPE_CAPS
759 * Gets the contents of @value.
761 * Returns: the contents of @value
764 gst_value_get_caps (const GValue * value)
766 g_return_val_if_fail (G_VALUE_TYPE (value) == GST_TYPE_CAPS, NULL);
768 return (GstCaps *) g_value_get_boxed (value);
771 /*************************************/
775 gst_value_compare_boolean (const GValue * value1, const GValue * value2)
777 if ((value1->data[0].v_int != 0) == (value2->data[0].v_int != 0))
778 return GST_VALUE_EQUAL;
779 return GST_VALUE_UNORDERED;
783 gst_value_serialize_boolean (const GValue * value)
785 if (value->data[0].v_int) {
786 return g_strdup ("true");
788 return g_strdup ("false");
792 gst_value_deserialize_boolean (GValue * dest, const char *s)
794 gboolean ret = FALSE;
796 if (g_ascii_strcasecmp (s, "true") == 0 ||
797 g_ascii_strcasecmp (s, "yes") == 0 ||
798 g_ascii_strcasecmp (s, "t") == 0 || strcmp (s, "1") == 0) {
799 g_value_set_boolean (dest, TRUE);
801 } else if (g_ascii_strcasecmp (s, "false") == 0 ||
802 g_ascii_strcasecmp (s, "no") == 0 ||
803 g_ascii_strcasecmp (s, "f") == 0 || strcmp (s, "0") == 0) {
804 g_value_set_boolean (dest, FALSE);
811 /*************************************/
815 gst_value_compare_int (const GValue * value1, const GValue * value2)
817 if (value1->data[0].v_int > value2->data[0].v_int)
818 return GST_VALUE_GREATER_THAN;
819 if (value1->data[0].v_int < value2->data[0].v_int)
820 return GST_VALUE_LESS_THAN;
821 return GST_VALUE_EQUAL;
825 gst_value_serialize_int (const GValue * value)
827 return g_strdup_printf ("%d", value->data[0].v_int);
831 gst_strtoi (const char *s, char **end, int base)
836 i = -(int) strtoul (s + 1, end, base);
838 i = strtoul (s, end, base);
845 gst_value_deserialize_int (GValue * dest, const char *s)
849 gboolean ret = FALSE;
851 x = gst_strtoi (s, &end, 0);
855 if (g_ascii_strcasecmp (s, "little_endian") == 0) {
858 } else if (g_ascii_strcasecmp (s, "big_endian") == 0) {
861 } else if (g_ascii_strcasecmp (s, "byte_order") == 0) {
864 } else if (g_ascii_strcasecmp (s, "min") == 0) {
867 } else if (g_ascii_strcasecmp (s, "max") == 0) {
873 g_value_set_int (dest, x);
878 /*************************************/
882 gst_value_compare_double (const GValue * value1, const GValue * value2)
884 if (value1->data[0].v_double > value2->data[0].v_double)
885 return GST_VALUE_GREATER_THAN;
886 if (value1->data[0].v_double < value2->data[0].v_double)
887 return GST_VALUE_LESS_THAN;
888 if (value1->data[0].v_double == value2->data[0].v_double)
889 return GST_VALUE_EQUAL;
890 return GST_VALUE_UNORDERED;
894 gst_value_serialize_double (const GValue * value)
896 char d[G_ASCII_DTOSTR_BUF_SIZE];
898 g_ascii_dtostr (d, G_ASCII_DTOSTR_BUF_SIZE, value->data[0].v_double);
903 gst_value_deserialize_double (GValue * dest, const char *s)
906 gboolean ret = FALSE;
909 x = g_ascii_strtod (s, &end);
913 if (g_ascii_strcasecmp (s, "min") == 0) {
916 } else if (g_ascii_strcasecmp (s, "max") == 0) {
922 g_value_set_double (dest, x);
927 /*************************************/
931 gst_value_compare_string (const GValue * value1, const GValue * value2)
933 int x = strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
936 return GST_VALUE_LESS_THAN;
938 return GST_VALUE_GREATER_THAN;
939 return GST_VALUE_EQUAL;
942 #define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
943 ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
947 gst_string_wrap (const char *s)
952 gboolean wrap = FALSE;
957 if (GST_ASCII_IS_STRING (*t)) {
959 } else if (*t < 0x20 || *t >= 0x7f) {
972 e = d = g_malloc (len + 3);
977 if (GST_ASCII_IS_STRING (*t)) {
979 } else if (*t < 0x20 || *t >= 0x7f) {
981 *e++ = '0' + ((*t) >> 6);
982 *e++ = '0' + (((*t) >> 3) & 0x7);
983 *e++ = '0' + ((*t++) & 0x7);
996 gst_value_serialize_string (const GValue * value)
998 return gst_string_wrap (value->data[0].v_pointer);
1002 gst_value_deserialize_string (GValue * dest, const char *s)
1004 g_value_set_string (dest, s);
1009 /*************************************/
1012 /*************************************/
1016 gst_value_intersect_int_int_range (GValue * dest, const GValue * src1,
1017 const GValue * src2)
1019 g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_INT, FALSE);
1020 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
1022 if (src2->data[0].v_int <= src1->data[0].v_int &&
1023 src2->data[1].v_int >= src1->data[0].v_int) {
1024 gst_value_init_and_copy (dest, src1);
1032 gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1,
1033 const GValue * src2)
1038 g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_INT_RANGE, FALSE);
1039 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_INT_RANGE, FALSE);
1041 min = MAX (src1->data[0].v_int, src2->data[0].v_int);
1042 max = MIN (src1->data[1].v_int, src2->data[1].v_int);
1045 g_value_init (dest, GST_TYPE_INT_RANGE);
1046 gst_value_set_int_range (dest, min, max);
1050 g_value_init (dest, G_TYPE_INT);
1051 g_value_set_int (dest, min);
1059 gst_value_intersect_double_double_range (GValue * dest, const GValue * src1,
1060 const GValue * src2)
1062 g_return_val_if_fail (G_VALUE_TYPE (src1) == G_TYPE_DOUBLE, FALSE);
1063 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_DOUBLE_RANGE, FALSE);
1065 if (src2->data[0].v_double <= src1->data[0].v_double &&
1066 src2->data[1].v_double >= src1->data[0].v_double) {
1067 gst_value_init_and_copy (dest, src1);
1075 gst_value_intersect_double_range_double_range (GValue * dest,
1076 const GValue * src1, const GValue * src2)
1081 g_return_val_if_fail (G_VALUE_TYPE (src1) == GST_TYPE_DOUBLE_RANGE, FALSE);
1082 g_return_val_if_fail (G_VALUE_TYPE (src2) == GST_TYPE_DOUBLE_RANGE, FALSE);
1084 min = MAX (src1->data[0].v_double, src2->data[0].v_double);
1085 max = MIN (src1->data[1].v_double, src2->data[1].v_double);
1088 g_value_init (dest, GST_TYPE_DOUBLE_RANGE);
1089 gst_value_set_double_range (dest, min, max);
1093 g_value_init (dest, G_TYPE_DOUBLE);
1094 g_value_set_int (dest, min);
1102 gst_value_intersect_list (GValue * dest, const GValue * value1,
1103 const GValue * value2)
1106 GValue intersection = { 0, };
1107 gboolean ret = FALSE;
1109 g_return_val_if_fail (GST_VALUE_HOLDS_LIST (value1), FALSE);
1111 size = gst_value_list_get_size (value1);
1112 for (i = 0; i < size; i++) {
1113 const GValue *cur = gst_value_list_get_value (value1, i);
1115 if (gst_value_intersect (&intersection, cur, value2)) {
1118 gst_value_init_and_copy (dest, &intersection);
1120 } else if (GST_VALUE_HOLDS_LIST (dest)) {
1121 gst_value_list_append_value (dest, &intersection);
1123 GValue temp = { 0, };
1125 gst_value_init_and_copy (&temp, dest);
1126 g_value_unset (dest);
1127 gst_value_list_concat (dest, &temp, &intersection);
1129 g_value_unset (&intersection);
1137 /*************************************/
1140 * gst_value_can_compare:
1141 * @value1: a value to compare
1142 * @value2: another value to compare
1144 * Determines if @value1 and @value2 can be compared.
1146 * Returns: TRUE if the values can be compared
1149 gst_value_can_compare (const GValue * value1, const GValue * value2)
1151 GstValueTable *table;
1154 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
1156 for (i = 0; i < gst_value_table->len; i++) {
1157 table = &g_array_index (gst_value_table, GstValueTable, i);
1158 if (table->type == G_VALUE_TYPE (value1) && table->compare)
1166 * gst_value_compare:
1167 * @value1: a value to compare
1168 * @value2: another value to compare
1170 * Compares @value1 and @value2. If @value1 and @value2 cannot be
1171 * compared, the function returns GST_VALUE_UNORDERED. Otherwise,
1172 * if @value1 is greater than @value2, GST_VALUE_GREATER is returned.
1173 * If @value1 is less than @value2, GST_VALUE_LESSER is returned.
1174 * If the values are equal, GST_VALUE_EQUAL is returned.
1176 * Returns: A GstValueCompareType value
1179 gst_value_compare (const GValue * value1, const GValue * value2)
1181 GstValueTable *table;
1184 if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
1185 return GST_VALUE_UNORDERED;
1187 for (i = 0; i < gst_value_table->len; i++) {
1188 table = &g_array_index (gst_value_table, GstValueTable, i);
1189 if (table->type != G_VALUE_TYPE (value1) || table->compare == NULL)
1192 return table->compare (value1, value2);
1195 g_critical ("unable to compare values of type %s\n",
1196 g_type_name (G_VALUE_TYPE (value1)));
1197 return GST_VALUE_UNORDERED;
1203 * gst_value_can_union:
1204 * @value1: a value to union
1205 * @value2: another value to union
1207 * Determines if @value1 and @value2 can be non-trivially unioned.
1208 * Any two values can be trivially unioned by adding both of them
1209 * to a GstValueList. However, certain types have the possibility
1210 * to be unioned in a simpler way. For example, an integer range
1211 * and an integer can be unioned if the integer is a subset of the
1212 * integer range. If there is the possibility that two values can
1213 * be unioned, this function returns TRUE.
1215 * Returns: TRUE if there is a function allowing the two values to
1219 gst_value_can_union (const GValue * value1, const GValue * value2)
1221 GstValueUnionInfo *union_info;
1224 for (i = 0; i < gst_value_union_funcs->len; i++) {
1225 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
1226 if (union_info->type1 == G_VALUE_TYPE (value1) &&
1227 union_info->type2 == G_VALUE_TYPE (value2))
1236 * @dest: the destination value
1237 * @value1: a value to union
1238 * @value2: another value to union
1240 * Creates a GValue cooresponding to the union of @value1 and @value2.
1242 * Returns: TRUE if the values could be unioned
1245 gst_value_union (GValue * dest, const GValue * value1, const GValue * value2)
1247 GstValueUnionInfo *union_info;
1250 for (i = 0; i < gst_value_union_funcs->len; i++) {
1251 union_info = &g_array_index (gst_value_union_funcs, GstValueUnionInfo, i);
1252 if (union_info->type1 == G_VALUE_TYPE (value1) &&
1253 union_info->type2 == G_VALUE_TYPE (value2)) {
1254 return union_info->func (dest, value1, value2);
1258 gst_value_list_concat (dest, value1, value2);
1263 * gst_value_register_union_func:
1264 * @type1: a type to union
1265 * @type2: another type to union
1266 * @func: a function that implments creating a union between the two types
1268 * Registers a union function that can create a union between GValues
1269 * of the type @type1 and @type2.
1273 gst_value_register_union_func (GType type1, GType type2, GstValueUnionFunc func)
1275 GstValueUnionInfo union_info;
1277 union_info.type1 = type1;
1278 union_info.type2 = type2;
1279 union_info.func = func;
1281 g_array_append_val (gst_value_union_funcs, union_info);
1287 * gst_value_can_intersect:
1294 gst_value_can_intersect (const GValue * value1, const GValue * value2)
1296 GstValueIntersectInfo *intersect_info;
1300 if (GST_VALUE_HOLDS_LIST (value1) || GST_VALUE_HOLDS_LIST (value2))
1303 for (i = 0; i < gst_value_intersect_funcs->len; i++) {
1304 intersect_info = &g_array_index (gst_value_intersect_funcs,
1305 GstValueIntersectInfo, i);
1306 if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
1307 intersect_info->type2 == G_VALUE_TYPE (value2))
1311 return gst_value_can_compare (value1, value2);
1315 * gst_value_intersect:
1316 * @dest: the destination value for intersection
1317 * @value1: a value to intersect
1318 * @value2: another value to intersect
1320 * Calculates the intersection of the two values.
1322 * Returns: TRUE if the intersection is non-empty
1325 gst_value_intersect (GValue * dest, const GValue * value1,
1326 const GValue * value2)
1328 GstValueIntersectInfo *intersect_info;
1332 /* special cases first */
1333 if (GST_VALUE_HOLDS_LIST (value1))
1334 return gst_value_intersect_list (dest, value1, value2);
1335 if (GST_VALUE_HOLDS_LIST (value2))
1336 return gst_value_intersect_list (dest, value2, value1);
1338 for (i = 0; i < gst_value_intersect_funcs->len; i++) {
1339 intersect_info = &g_array_index (gst_value_intersect_funcs,
1340 GstValueIntersectInfo, i);
1341 if (intersect_info->type1 == G_VALUE_TYPE (value1) &&
1342 intersect_info->type2 == G_VALUE_TYPE (value2)) {
1343 ret = intersect_info->func (dest, value1, value2);
1346 if (intersect_info->type1 == G_VALUE_TYPE (value2) &&
1347 intersect_info->type2 == G_VALUE_TYPE (value1)) {
1348 ret = intersect_info->func (dest, value2, value1);
1353 if (gst_value_compare (value1, value2) == GST_VALUE_EQUAL) {
1354 gst_value_init_and_copy (dest, value1);
1362 * gst_value_register_intersection_func:
1369 gst_value_register_intersect_func (GType type1, GType type2,
1370 GstValueIntersectFunc func)
1372 GstValueIntersectInfo intersect_info;
1374 intersect_info.type1 = type1;
1375 intersect_info.type2 = type2;
1376 intersect_info.func = func;
1378 g_array_append_val (gst_value_intersect_funcs, intersect_info);
1382 * gst_value_register:
1387 gst_value_register (const GstValueTable * table)
1389 g_array_append_val (gst_value_table, *table);
1393 * gst_value_init_and_copy:
1399 gst_value_init_and_copy (GValue * dest, const GValue * src)
1401 g_value_init (dest, G_VALUE_TYPE (src));
1402 g_value_copy (src, dest);
1406 * gst_value_serialize:
1412 gst_value_serialize (const GValue * value)
1415 GValue s_val = { 0 };
1416 GstValueTable *table;
1419 for (i = 0; i < gst_value_table->len; i++) {
1420 table = &g_array_index (gst_value_table, GstValueTable, i);
1421 if (table->type != G_VALUE_TYPE (value) || table->serialize == NULL)
1424 return table->serialize (value);
1427 g_value_init (&s_val, G_TYPE_STRING);
1428 g_value_transform (value, &s_val);
1429 s = gst_string_wrap (g_value_get_string (&s_val));
1430 g_value_unset (&s_val);
1436 * gst_value_deserialize:
1443 gst_value_deserialize (GValue * dest, const gchar * src)
1445 GstValueTable *table;
1448 for (i = 0; i < gst_value_table->len; i++) {
1449 table = &g_array_index (gst_value_table, GstValueTable, i);
1450 if (table->type != G_VALUE_TYPE (dest) || table->deserialize == NULL)
1453 return table->deserialize (dest, src);
1460 _gst_value_initialize (void)
1475 //const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_DERIVABLE, };
1477 gst_value_table = g_array_new (FALSE, FALSE, sizeof (GstValueTable));
1478 gst_value_union_funcs = g_array_new (FALSE, FALSE,
1479 sizeof (GstValueUnionInfo));
1480 gst_value_intersect_funcs = g_array_new (FALSE, FALSE,
1481 sizeof (GstValueIntersectInfo));
1484 static const GTypeValueTable value_table = {
1485 gst_value_init_fourcc,
1487 gst_value_copy_fourcc,
1490 gst_value_collect_fourcc,
1492 gst_value_lcopy_fourcc
1494 static GstValueTable gst_value = {
1496 gst_value_compare_fourcc,
1497 gst_value_serialize_fourcc,
1498 gst_value_deserialize_fourcc,
1501 info.value_table = &value_table;
1503 g_type_register_static (G_TYPE_BOXED, "GstFourcc", &info, 0);
1504 gst_value.type = gst_type_fourcc;
1505 gst_value_register (&gst_value);
1509 static const GTypeValueTable value_table = {
1510 gst_value_init_int_range,
1512 gst_value_copy_int_range,
1515 gst_value_collect_int_range,
1517 gst_value_lcopy_int_range
1519 static GstValueTable gst_value = {
1521 gst_value_compare_int_range,
1522 gst_value_serialize_int_range,
1523 gst_value_deserialize_int_range,
1526 info.value_table = &value_table;
1527 gst_type_int_range =
1528 g_type_register_static (G_TYPE_BOXED, "GstIntRange", &info, 0);
1529 gst_value.type = gst_type_int_range;
1530 gst_value_register (&gst_value);
1534 static const GTypeValueTable value_table = {
1535 gst_value_init_double_range,
1537 gst_value_copy_double_range,
1540 gst_value_collect_double_range,
1542 gst_value_lcopy_double_range
1544 static GstValueTable gst_value = {
1546 gst_value_compare_double_range,
1547 gst_value_serialize_double_range,
1548 gst_value_deserialize_double_range,
1551 info.value_table = &value_table;
1552 gst_type_double_range =
1553 g_type_register_static (G_TYPE_BOXED, "GstDoubleRange", &info, 0);
1554 gst_value.type = gst_type_double_range;
1555 gst_value_register (&gst_value);
1559 static const GTypeValueTable value_table = {
1560 gst_value_init_list,
1561 gst_value_free_list,
1562 gst_value_copy_list,
1563 gst_value_list_peek_pointer,
1565 gst_value_collect_list,
1567 gst_value_lcopy_list
1569 static GstValueTable gst_value = {
1571 gst_value_compare_list,
1572 gst_value_serialize_list,
1573 gst_value_deserialize_list,
1576 info.value_table = &value_table;
1578 g_type_register_static (G_TYPE_BOXED, "GstValueList", &info, 0);
1579 gst_value.type = gst_type_list;
1580 gst_value_register (&gst_value);
1584 static const GstValueTable gst_value = {
1586 gst_value_compare_int,
1587 gst_value_serialize_int,
1588 gst_value_deserialize_int,
1591 gst_value_register (&gst_value);
1595 static const GstValueTable gst_value = {
1597 gst_value_compare_double,
1598 gst_value_serialize_double,
1599 gst_value_deserialize_double,
1602 gst_value_register (&gst_value);
1606 static const GstValueTable gst_value = {
1608 gst_value_compare_string,
1609 gst_value_serialize_string,
1610 gst_value_deserialize_string,
1613 gst_value_register (&gst_value);
1617 static const GstValueTable gst_value = {
1619 gst_value_compare_boolean,
1620 gst_value_serialize_boolean,
1621 gst_value_deserialize_boolean,
1624 gst_value_register (&gst_value);
1627 g_value_register_transform_func (GST_TYPE_FOURCC, G_TYPE_STRING,
1628 gst_value_transform_fourcc_string);
1629 g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING,
1630 gst_value_transform_int_range_string);
1631 g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING,
1632 gst_value_transform_double_range_string);
1633 g_value_register_transform_func (GST_TYPE_LIST, G_TYPE_STRING,
1634 gst_value_transform_list_string);
1636 gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
1637 gst_value_intersect_int_int_range);
1638 gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
1639 gst_value_intersect_int_range_int_range);
1640 gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE,
1641 gst_value_intersect_double_double_range);
1642 gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE,
1643 GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_range_double_range);