1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4 * Copyright (C) John Stebbins 2008 <stebbins@stebbins>
6 * presets.c is free software.
8 * You may redistribute it and/or modify it under the terms of the
9 * GNU General Public License, as published by the Free Software
10 * Foundation; either version 2 of the License, or (at your option)
16 #include <glib-object.h>
21 static void dict_delete_key(gpointer data);
22 static void dict_delete_value(gpointer data);
25 ghb_value_new(GType gtype)
27 GValue *gval = g_malloc0(sizeof(GValue));
28 g_value_init(gval, gtype);
33 ghb_value_free(GValue *gval)
35 if (gval == NULL) return;
41 ghb_value_dup(const GValue *val)
43 if (val == NULL) return NULL;
44 GValue *copy = ghb_value_new(G_VALUE_TYPE(val));
45 g_value_copy(val, copy);
50 debug_show_type(GType tp)
52 const gchar *str = "unknown";
53 if (tp == G_TYPE_STRING)
57 else if (tp == G_TYPE_INT)
61 else if (tp == G_TYPE_INT64)
65 else if (tp == G_TYPE_DOUBLE)
69 else if (tp == G_TYPE_BOOLEAN)
73 else if (tp == ghb_array_get_type())
77 else if (tp == ghb_dict_get_type())
81 g_debug("Type %s", str);
85 debug_show_value(GValue *gval)
89 tp = G_VALUE_TYPE(gval);
90 if (tp == G_TYPE_STRING)
92 g_message("Type %s value %s", "string", g_value_get_string(gval));
94 else if (tp == G_TYPE_INT)
96 g_message("Type %s value %d", "int", g_value_get_int(gval));
98 else if (tp == G_TYPE_INT64)
100 g_message("Type %s value %" PRId64, "int64", g_value_get_int64(gval));
102 else if (tp == G_TYPE_DOUBLE)
104 g_message("Type %s value %f", "double", g_value_get_double(gval));
106 else if (tp == G_TYPE_BOOLEAN)
108 g_message("Type %s value %d", "boolean", g_value_get_boolean(gval));
110 else if (tp == ghb_array_get_type())
112 g_message("Type %s", "boolean");
114 else if (tp == ghb_dict_get_type())
116 g_message("Type %s", "dict");
121 ghb_value_int(const GValue *val)
125 if (val == NULL) return 0;
127 if (G_VALUE_TYPE(val) != G_TYPE_INT)
129 g_value_init(&xform, G_TYPE_INT);
130 if (!g_value_transform(val, &xform))
132 debug_show_type(G_VALUE_TYPE(val));
133 g_warning("int can't transform");
136 result = g_value_get_int(&xform);
137 g_value_unset(&xform);
141 result = g_value_get_int(val);
147 ghb_value_int64(const GValue *val)
151 if (val == NULL) return 0;
153 if (G_VALUE_TYPE(val) != G_TYPE_INT64)
155 g_value_init(&xform, G_TYPE_INT64);
156 if (!g_value_transform(val, &xform))
158 debug_show_type(G_VALUE_TYPE(val));
159 g_warning("int64 can't transform");
162 result = g_value_get_int64(&xform);
163 g_value_unset(&xform);
167 result = g_value_get_int64(val);
173 ghb_value_double(const GValue *val)
177 if (val == NULL) return 0;
179 if (G_VALUE_TYPE(val) != G_TYPE_DOUBLE)
181 g_value_init(&xform, G_TYPE_DOUBLE);
182 if (!g_value_transform(val, &xform))
184 debug_show_type(G_VALUE_TYPE(val));
185 g_warning("double can't transform");
188 result = g_value_get_double(&xform);
189 g_value_unset(&xform);
193 result = g_value_get_double(val);
199 ghb_value_string(const GValue *val)
203 if (val == NULL) return 0;
205 if (G_VALUE_TYPE(val) != G_TYPE_STRING)
207 g_value_init(&xform, G_TYPE_STRING);
208 if (!g_value_transform(val, &xform))
210 debug_show_type(G_VALUE_TYPE(val));
211 g_warning("string can't transform");
214 result = g_strdup(g_value_get_string(&xform));
215 g_value_unset(&xform);
219 result = g_strdup(g_value_get_string(val));
225 ghb_value_boolean(const GValue *val)
229 if (val == NULL) return FALSE;
231 if (G_VALUE_TYPE(val) != G_TYPE_BOOLEAN)
233 g_value_init(&xform, G_TYPE_BOOLEAN);
234 if (!g_value_transform(val, &xform))
236 debug_show_type(G_VALUE_TYPE(val));
237 g_warning("boolean can't transform");
240 result = g_value_get_boolean(&xform);
241 g_value_unset(&xform);
245 result = g_value_get_boolean(val);
251 ghb_value_cmp(const GValue *vala, const GValue *valb)
256 if ((vala == NULL && valb != NULL) || (vala != NULL && valb == NULL))
260 typa = G_VALUE_TYPE(vala);
261 typb = G_VALUE_TYPE(valb);
267 if (typa == G_TYPE_STRING)
271 stra = ghb_value_string(vala);
272 strb = ghb_value_string(valb);
273 if (stra == NULL && strb == NULL)
285 res = strcmp(stra, strb);
290 else if (typa == G_TYPE_INT64 || typa == G_TYPE_INT ||
291 typa == G_TYPE_BOOLEAN)
293 return ghb_value_int64(vala) - ghb_value_int64(valb);
295 else if (typa == G_TYPE_DOUBLE || typa == G_TYPE_FLOAT)
297 return ghb_value_double(vala) - ghb_value_double(valb);
299 else if (typa == ghb_array_get_type())
301 // Cheating here. Just assume they are different.
302 // Maybe later I'll recurse through these
305 else if (typa == ghb_dict_get_type())
307 // Cheating here. Just assume they are different.
308 // Maybe later I'll recurse through these
313 g_warning("ghb_value_cmp: unrecognized type");
320 ghb_string_value(const gchar *str)
322 static GValue gval = {0,};
323 if (!G_IS_VALUE(&gval))
324 g_value_init(&gval, G_TYPE_STRING);
325 g_value_set_string(&gval, str);
330 ghb_int64_value(gint64 ival)
332 static GValue gval = {0,};
333 if (!G_IS_VALUE(&gval))
334 g_value_init(&gval, G_TYPE_INT64);
335 g_value_set_int64(&gval, ival);
340 ghb_int_value(gint ival)
342 static GValue gval = {0,};
343 if (!G_IS_VALUE(&gval))
344 g_value_init(&gval, G_TYPE_INT64);
345 g_value_set_int64(&gval, (gint64)ival);
350 ghb_double_value(gdouble dval)
352 static GValue gval = {0,};
353 if (!G_IS_VALUE(&gval))
354 g_value_init(&gval, G_TYPE_DOUBLE);
355 g_value_set_double(&gval, dval);
360 ghb_boolean_value(gboolean bval)
362 static GValue gval = {0,};
363 if (!G_IS_VALUE(&gval))
364 g_value_init(&gval, G_TYPE_BOOLEAN);
365 g_value_set_boolean(&gval, bval);
370 ghb_string_value_new(const gchar *str)
372 if (str == NULL) str = "";
373 GValue *gval = ghb_value_new(G_TYPE_STRING);
374 g_value_set_string(gval, str);
379 ghb_int64_value_new(gint64 ival)
381 GValue *gval = ghb_value_new(G_TYPE_INT64);
382 g_value_set_int64(gval, ival);
387 ghb_int_value_new(gint ival)
389 GValue *gval = ghb_value_new(G_TYPE_INT64);
390 g_value_set_int64(gval, ival);
395 ghb_double_value_new(gdouble dval)
397 GValue *gval = ghb_value_new(G_TYPE_DOUBLE);
398 g_value_set_double(gval, dval);
403 ghb_boolean_value_new(gboolean bval)
405 GValue *gval = ghb_value_new(G_TYPE_BOOLEAN);
406 g_value_set_boolean(gval, bval);
414 GValue *gval = ghb_value_new(ghb_dict_get_type());
415 dict = g_hash_table_new_full(g_str_hash, g_str_equal,
416 dict_delete_key, dict_delete_value);
417 g_value_take_boxed(gval, dict);
422 ghb_array_value_new(guint size)
424 GValue *gval = ghb_value_new(ghb_array_get_type());
427 array = g_array_sized_new(FALSE, FALSE, sizeof(GValue*), size);
428 g_value_take_boxed(gval, array);
433 ghb_array_value_reset(GValue *gval, guint size)
437 array = g_array_sized_new(FALSE, FALSE, sizeof(GValue*), size);
438 g_value_take_boxed(gval, array);
442 ghb_date_value_new(GDate *date)
444 GValue *gval = ghb_value_new(g_date_get_type());
445 g_value_set_boxed(gval, date);
450 ghb_rawdata_value_new(ghb_rawdata_t *data)
452 GValue *gval = ghb_value_new(ghb_rawdata_get_type());
453 g_value_take_boxed(gval, data);
458 rawdata_copy(gpointer boxed)
460 const ghb_rawdata_t *data = (const ghb_rawdata_t*)boxed;
461 ghb_rawdata_t *copy = g_malloc(sizeof(ghb_rawdata_t));
462 copy->size = data->size;
465 copy->data = g_malloc(data->size);
466 memcpy(copy->data, data->data, data->size);
477 rawdata_free(gpointer boxed)
479 ghb_rawdata_t *data = (ghb_rawdata_t*)boxed;
480 if (data->data) g_free(data->data);
486 ghb_rawdata_get_type(void)
488 static GType type_id = 0;
490 type_id = g_boxed_type_register_static(g_intern_static_string("GHBData"),
491 (GBoxedCopyFunc) rawdata_copy,
492 (GBoxedFreeFunc) rawdata_free);
497 dict_delete_key(gpointer data)
501 g_warning("dict frees null key");
508 dict_delete_value(gpointer data)
510 GValue *gval = (GValue*)data;
513 g_warning("dict frees null value");
516 ghb_value_free(gval);
520 dict_copy(gpointer boxed)
522 GHashTable *dict = (GHashTable*)boxed;
528 copy = g_hash_table_new_full(g_str_hash, g_str_equal,
529 dict_delete_key, dict_delete_value);
531 g_hash_table_iter_init(&iter, dict);
532 // middle (void*) cast prevents gcc warning "defreferencing type-punned
533 // pointer will break strict-aliasing rules"
534 while (g_hash_table_iter_next(
535 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
537 g_hash_table_insert(copy, g_strdup(key), ghb_value_dup(gval));
543 dict_free(gpointer boxed)
545 GHashTable *dict = (GHashTable*)boxed;
546 g_hash_table_destroy(dict);
551 ghb_dict_get_type(void)
553 static GType type_id = 0;
555 type_id = g_boxed_type_register_static(
556 g_intern_static_string("GHBDict"),
557 (GBoxedCopyFunc) dict_copy,
558 (GBoxedFreeFunc) dict_free);
563 ghb_dict_insert(GValue *gval, gchar *key, GValue *val)
565 GHashTable *dict = g_value_get_boxed(gval);
566 g_hash_table_insert(dict, key, val);
570 ghb_dict_iter_init(GHashTableIter *iter, GValue *gval)
572 GHashTable *dict = g_value_get_boxed(gval);
573 g_hash_table_iter_init(iter, dict);
577 ghb_dict_lookup(const GValue *gval, const gchar *key)
579 GHashTable *dict = g_value_get_boxed(gval);
580 return g_hash_table_lookup(dict, key);
584 ghb_dict_remove(GValue *gval, const gchar *key)
586 GHashTable *dict = g_value_get_boxed(gval);
587 return g_hash_table_remove(dict, key);
591 array_copy(gpointer boxed)
593 const GArray *array = (const GArray*)boxed;
594 GArray *copy = g_array_new(FALSE, FALSE, sizeof(GValue*));
596 GValue *gval, *gval_copy;
599 for (ii = 0; ii < array->len; ii++)
601 gval = g_array_index(array, GValue*, ii);
604 gval_copy = ghb_value_dup(gval);
605 g_array_append_val(copy, gval_copy);
612 array_free(gpointer boxed)
614 GArray *array = (GArray*)boxed;
618 for (ii = 0; ii < array->len; ii++)
620 gval = g_array_index(array, GValue*, ii);
623 ghb_value_free(gval);
626 g_array_free(array, TRUE);
631 ghb_array_get_type(void)
633 static GType type_id = 0;
635 type_id = g_boxed_type_register_static(
636 g_intern_static_string("GHBArray"),
637 (GBoxedCopyFunc) array_copy,
638 (GBoxedFreeFunc) array_free);
643 ghb_array_get_nth(const GValue *gval, gint ii)
645 GArray *arr = g_value_get_boxed(gval);
646 return g_array_index(arr, GValue*, ii);
650 ghb_array_insert(GValue *gval, guint ii, GValue *val)
652 GArray *arr = g_value_get_boxed(gval);
653 // A little nastyness here. The array pointer
654 // can change when the array changes size. So
655 // I must re-box it in the GValue each time.
656 arr = g_array_insert_val(arr, ii, val);
657 memset(gval, 0, sizeof(GValue));
658 g_value_init(gval, ghb_array_get_type());
659 g_value_take_boxed(gval, arr);
663 ghb_array_append(GValue *gval, GValue *val)
665 GArray *arr = g_value_get_boxed(gval);
666 // A little nastyness here. The array pointer
667 // can change when the array changes size. So
668 // I must re-box it in the GValue each time.
669 arr = g_array_append_val(arr, val);
670 memset(gval, 0, sizeof(GValue));
671 g_value_init(gval, ghb_array_get_type());
672 g_value_take_boxed(gval, arr);
676 ghb_array_remove(GValue *gval, guint ii)
678 GArray *arr = g_value_get_boxed(gval);
679 // A little nastyness here. The array pointer
680 // can change when the array changes size. So
681 // I must re-box it in the GValue each time.
682 arr = g_array_remove_index(arr, ii);
683 memset(gval, 0, sizeof(GValue));
684 g_value_init(gval, ghb_array_get_type());
685 g_value_take_boxed(gval, arr);
689 ghb_array_replace(GValue *gval, guint ii, GValue *val)
691 GArray *arr = g_value_get_boxed(gval);
692 // A little nastyness here. The array pointer
693 // can change when the array changes size. So
694 // I must re-box it in the GValue each time.
695 if (ii >= arr->len) return;
696 ghb_value_free(((GValue**)arr->data)[ii]);
697 ((GValue**)arr->data)[ii] = val;
701 ghb_array_copy(GValue *arr1, GValue *arr2, gint count)
705 // empty the first array if it is not already empty
706 len = ghb_array_len(arr1);
707 for (ii = 0; ii < len; ii++)
708 ghb_array_remove(arr1, 0);
710 len = ghb_array_len(arr2);
711 count = MIN(count, len);
712 for (ii = 0; ii < count; ii++)
713 ghb_array_append(arr1, ghb_value_dup(ghb_array_get_nth(arr2, ii)));
717 ghb_array_len(const GValue *gval)
719 if (gval == NULL) return 0;
720 GArray *arr = g_value_get_boxed(gval);
725 xform_string_int(const GValue *sval, GValue *ival)
729 const gchar *str = g_value_get_string(sval);
730 gint val = g_strtod(str, &end);
732 val = (guint)(~0)>>1;
733 g_value_set_int(ival, val);
737 xform_string_int64(const GValue *sval, GValue *ival)
740 const gchar *str = g_value_get_string(sval);
741 gint64 val = g_strtod(str, &end);
743 val = (guint64)(~0L)>>1;
744 g_value_set_int64(ival, val);
748 xform_string_double(const GValue *sval, GValue *dval)
750 const gchar *str = g_value_get_string(sval);
751 double val = g_strtod(str, NULL);
752 g_value_set_double(dval, val);
756 xform_boolean_double(const GValue *bval, GValue *dval)
758 gboolean b = g_value_get_boolean(bval);
760 g_value_set_double(dval, val);
764 ghb_register_transforms()
766 g_value_register_transform_func(G_TYPE_STRING, G_TYPE_INT64,
768 g_value_register_transform_func(G_TYPE_STRING, G_TYPE_INT,
770 g_value_register_transform_func(G_TYPE_STRING, G_TYPE_DOUBLE,
771 xform_string_double);
772 g_value_register_transform_func(G_TYPE_BOOLEAN, G_TYPE_DOUBLE,
773 xform_boolean_double);