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>
20 static void dict_delete_key(gpointer data);
21 static void dict_delete_value(gpointer data);
24 ghb_value_new(GType gtype)
26 GValue *gval = g_malloc0(sizeof(GValue));
27 g_value_init(gval, gtype);
32 ghb_value_free(GValue *gval)
34 if (gval == NULL) return;
40 ghb_value_dup(const GValue *val)
42 if (val == NULL) return NULL;
43 GValue *copy = ghb_value_new(G_VALUE_TYPE(val));
44 g_value_copy(val, copy);
49 debug_show_type(GType tp)
51 const gchar *str = "unknown";
52 if (tp == G_TYPE_STRING)
56 else if (tp == G_TYPE_INT)
60 else if (tp == G_TYPE_INT64)
64 else if (tp == G_TYPE_DOUBLE)
68 else if (tp == G_TYPE_BOOLEAN)
72 else if (tp == ghb_array_get_type())
76 else if (tp == ghb_dict_get_type())
84 ghb_value_int(const GValue *val)
88 if (val == NULL) return 0;
90 if (G_VALUE_TYPE(val) != G_TYPE_INT)
92 g_value_init(&xform, G_TYPE_INT);
93 if (!g_value_transform(val, &xform))
95 debug_show_type(G_VALUE_TYPE(val));
96 g_warning("int can't transform");
99 result = g_value_get_int(&xform);
100 g_value_unset(&xform);
104 result = g_value_get_int(val);
110 ghb_value_int64(const GValue *val)
114 if (val == NULL) return 0;
116 if (G_VALUE_TYPE(val) != G_TYPE_INT64)
118 g_value_init(&xform, G_TYPE_INT64);
119 if (!g_value_transform(val, &xform))
121 debug_show_type(G_VALUE_TYPE(val));
122 g_warning("int64 can't transform");
125 result = g_value_get_int64(&xform);
126 g_value_unset(&xform);
130 result = g_value_get_int64(val);
136 ghb_value_double(const GValue *val)
140 if (val == NULL) return 0;
142 if (G_VALUE_TYPE(val) != G_TYPE_DOUBLE)
144 g_value_init(&xform, G_TYPE_DOUBLE);
145 if (!g_value_transform(val, &xform))
147 debug_show_type(G_VALUE_TYPE(val));
148 g_warning("double can't transform");
151 result = g_value_get_double(&xform);
152 g_value_unset(&xform);
156 result = g_value_get_double(val);
162 ghb_value_string(const GValue *val)
166 if (val == NULL) return 0;
168 if (G_VALUE_TYPE(val) != G_TYPE_STRING)
170 g_value_init(&xform, G_TYPE_STRING);
171 if (!g_value_transform(val, &xform))
173 debug_show_type(G_VALUE_TYPE(val));
174 g_warning("string can't transform");
177 result = g_strdup(g_value_get_string(&xform));
178 g_value_unset(&xform);
182 result = g_strdup(g_value_get_string(val));
188 ghb_value_boolean(const GValue *val)
192 if (val == NULL) return FALSE;
194 if (G_VALUE_TYPE(val) != G_TYPE_BOOLEAN)
196 g_value_init(&xform, G_TYPE_BOOLEAN);
197 if (!g_value_transform(val, &xform))
199 debug_show_type(G_VALUE_TYPE(val));
200 g_warning("boolean can't transform");
203 result = g_value_get_boolean(&xform);
204 g_value_unset(&xform);
208 result = g_value_get_boolean(val);
214 ghb_value_cmp(const GValue *vala, const GValue *valb)
219 typa = G_VALUE_TYPE(vala);
220 typb = G_VALUE_TYPE(valb);
226 if (typa == G_TYPE_STRING)
230 stra = ghb_value_string(vala);
231 strb = ghb_value_string(valb);
232 if (stra == NULL && strb == NULL)
244 res = strcmp(stra, strb);
249 else if (typa == G_TYPE_INT64 || typa == G_TYPE_INT ||
250 typa == G_TYPE_BOOLEAN)
252 return ghb_value_int64(vala) - ghb_value_int64(valb);
254 else if (typa == G_TYPE_DOUBLE || typa == G_TYPE_FLOAT)
256 return ghb_value_double(vala) - ghb_value_double(valb);
258 else if (typa == ghb_array_get_type())
260 // Cheating here. Just assume they are different.
261 // Maybe later I'll recurse through these
264 else if (typa == ghb_dict_get_type())
266 // Cheating here. Just assume they are different.
267 // Maybe later I'll recurse through these
272 g_warning("ghb_value_cmp: unrecognized type");
279 ghb_string_value(const gchar *str)
281 static GValue gval = {0,};
282 if (!G_IS_VALUE(&gval))
283 g_value_init(&gval, G_TYPE_STRING);
284 g_value_set_string(&gval, str);
289 ghb_int64_value(gint64 ival)
291 static GValue gval = {0,};
292 if (!G_IS_VALUE(&gval))
293 g_value_init(&gval, G_TYPE_INT64);
294 g_value_set_int64(&gval, ival);
299 ghb_int_value(gint ival)
301 static GValue gval = {0,};
302 if (!G_IS_VALUE(&gval))
303 g_value_init(&gval, G_TYPE_INT64);
304 g_value_set_int64(&gval, (gint64)ival);
309 ghb_double_value(gdouble dval)
311 static GValue gval = {0,};
312 if (!G_IS_VALUE(&gval))
313 g_value_init(&gval, G_TYPE_DOUBLE);
314 g_value_set_double(&gval, dval);
319 ghb_boolean_value(gboolean bval)
321 static GValue gval = {0,};
322 if (!G_IS_VALUE(&gval))
323 g_value_init(&gval, G_TYPE_BOOLEAN);
324 g_value_set_boolean(&gval, bval);
329 ghb_string_value_new(const gchar *str)
331 if (str == NULL) str = "";
332 GValue *gval = ghb_value_new(G_TYPE_STRING);
333 g_value_set_string(gval, str);
338 ghb_int64_value_new(gint64 ival)
340 GValue *gval = ghb_value_new(G_TYPE_INT64);
341 g_value_set_int64(gval, ival);
346 ghb_int_value_new(gint ival)
348 GValue *gval = ghb_value_new(G_TYPE_INT64);
349 g_value_set_int64(gval, ival);
354 ghb_double_value_new(gdouble dval)
356 GValue *gval = ghb_value_new(G_TYPE_DOUBLE);
357 g_value_set_double(gval, dval);
362 ghb_boolean_value_new(gboolean bval)
364 GValue *gval = ghb_value_new(G_TYPE_BOOLEAN);
365 g_value_set_boolean(gval, bval);
373 GValue *gval = ghb_value_new(ghb_dict_get_type());
374 dict = g_hash_table_new_full(g_str_hash, g_str_equal,
375 dict_delete_key, dict_delete_value);
376 g_value_take_boxed(gval, dict);
381 ghb_array_value_new(guint size)
383 GValue *gval = ghb_value_new(ghb_array_get_type());
386 array = g_array_sized_new(FALSE, FALSE, sizeof(GValue*), size);
387 g_value_take_boxed(gval, array);
392 ghb_array_value_reset(GValue *gval, guint size)
396 array = g_array_sized_new(FALSE, FALSE, sizeof(GValue*), size);
397 g_value_take_boxed(gval, array);
401 ghb_date_value_new(GDate *date)
403 GValue *gval = ghb_value_new(g_date_get_type());
404 g_value_set_boxed(gval, date);
409 ghb_rawdata_value_new(ghb_rawdata_t *data)
411 GValue *gval = ghb_value_new(ghb_rawdata_get_type());
412 g_value_take_boxed(gval, data);
417 rawdata_copy(gpointer boxed)
419 const ghb_rawdata_t *data = (const ghb_rawdata_t*)boxed;
420 ghb_rawdata_t *copy = g_malloc(sizeof(ghb_rawdata_t));
421 copy->size = data->size;
424 copy->data = g_malloc(data->size);
425 memcpy(copy->data, data->data, data->size);
436 rawdata_free(gpointer boxed)
438 ghb_rawdata_t *data = (ghb_rawdata_t*)boxed;
439 if (data->data) g_free(data->data);
445 ghb_rawdata_get_type(void)
447 static GType type_id = 0;
449 type_id = g_boxed_type_register_static(g_intern_static_string("GHBData"),
450 (GBoxedCopyFunc) rawdata_copy,
451 (GBoxedFreeFunc) rawdata_free);
456 dict_delete_key(gpointer data)
460 g_warning("dict frees null key");
467 dict_delete_value(gpointer data)
469 GValue *gval = (GValue*)data;
472 g_warning("dict frees null value");
475 ghb_value_free(gval);
479 dict_copy(gpointer boxed)
481 GHashTable *dict = (GHashTable*)boxed;
487 copy = g_hash_table_new_full(g_str_hash, g_str_equal,
488 dict_delete_key, dict_delete_value);
490 g_hash_table_iter_init(&iter, dict);
491 // middle (void*) cast prevents gcc warning "defreferencing type-punned
492 // pointer will break strict-aliasing rules"
493 while (g_hash_table_iter_next(
494 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
496 g_hash_table_insert(copy, g_strdup(key), ghb_value_dup(gval));
502 dict_free(gpointer boxed)
504 GHashTable *dict = (GHashTable*)boxed;
505 g_hash_table_destroy(dict);
510 ghb_dict_get_type(void)
512 static GType type_id = 0;
514 type_id = g_boxed_type_register_static(
515 g_intern_static_string("GHBDict"),
516 (GBoxedCopyFunc) dict_copy,
517 (GBoxedFreeFunc) dict_free);
522 ghb_dict_insert(GValue *gval, gchar *key, GValue *val)
524 GHashTable *dict = g_value_get_boxed(gval);
525 g_hash_table_insert(dict, key, val);
529 ghb_dict_iter_init(GHashTableIter *iter, GValue *gval)
531 GHashTable *dict = g_value_get_boxed(gval);
532 g_hash_table_iter_init(iter, dict);
536 ghb_dict_lookup(GValue *gval, const gchar *key)
538 GHashTable *dict = g_value_get_boxed(gval);
539 return g_hash_table_lookup(dict, key);
543 ghb_dict_remove(GValue *gval, const gchar *key)
545 GHashTable *dict = g_value_get_boxed(gval);
546 return g_hash_table_remove(dict, key);
550 array_copy(gpointer boxed)
552 const GArray *array = (const GArray*)boxed;
553 GArray *copy = g_array_new(FALSE, FALSE, sizeof(GValue*));
555 GValue *gval, *gval_copy;
558 for (ii = 0; ii < array->len; ii++)
560 gval = g_array_index(array, GValue*, ii);
563 gval_copy = ghb_value_dup(gval);
564 g_array_append_val(copy, gval_copy);
571 array_free(gpointer boxed)
573 GArray *array = (GArray*)boxed;
577 for (ii = 0; ii < array->len; ii++)
579 gval = g_array_index(array, GValue*, ii);
582 ghb_value_free(gval);
585 g_array_free(array, TRUE);
590 ghb_array_get_type(void)
592 static GType type_id = 0;
594 type_id = g_boxed_type_register_static(
595 g_intern_static_string("GHBArray"),
596 (GBoxedCopyFunc) array_copy,
597 (GBoxedFreeFunc) array_free);
602 ghb_array_get_nth(const GValue *gval, gint ii)
604 GArray *arr = g_value_get_boxed(gval);
605 return g_array_index(arr, GValue*, ii);
609 ghb_array_insert(GValue *gval, guint ii, GValue *val)
611 GArray *arr = g_value_get_boxed(gval);
612 // A little nastyness here. The array pointer
613 // can change when the array changes size. So
614 // I must re-box it in the GValue each time.
615 arr = g_array_insert_val(arr, ii, val);
616 memset(gval, 0, sizeof(GValue));
617 g_value_init(gval, ghb_array_get_type());
618 g_value_take_boxed(gval, arr);
622 ghb_array_append(GValue *gval, GValue *val)
624 GArray *arr = g_value_get_boxed(gval);
625 // A little nastyness here. The array pointer
626 // can change when the array changes size. So
627 // I must re-box it in the GValue each time.
628 arr = g_array_append_val(arr, val);
629 memset(gval, 0, sizeof(GValue));
630 g_value_init(gval, ghb_array_get_type());
631 g_value_take_boxed(gval, arr);
635 ghb_array_remove(GValue *gval, guint ii)
637 GArray *arr = g_value_get_boxed(gval);
638 // A little nastyness here. The array pointer
639 // can change when the array changes size. So
640 // I must re-box it in the GValue each time.
641 arr = g_array_remove_index(arr, ii);
642 memset(gval, 0, sizeof(GValue));
643 g_value_init(gval, ghb_array_get_type());
644 g_value_take_boxed(gval, arr);
648 ghb_array_replace(GValue *gval, guint ii, GValue *val)
650 GArray *arr = g_value_get_boxed(gval);
651 // A little nastyness here. The array pointer
652 // can change when the array changes size. So
653 // I must re-box it in the GValue each time.
654 if (ii >= arr->len) return;
655 ghb_value_free(((GValue**)arr->data)[ii]);
656 ((GValue**)arr->data)[ii] = val;
660 ghb_array_copy(GValue *arr1, GValue *arr2, gint count)
664 // empty the first array if it is not already empty
665 len = ghb_array_len(arr1);
666 for (ii = 0; ii < len; ii++)
667 ghb_array_remove(arr1, 0);
669 len = ghb_array_len(arr2);
670 count = MIN(count, len);
671 for (ii = 0; ii < count; ii++)
672 ghb_array_append(arr1, ghb_value_dup(ghb_array_get_nth(arr2, ii)));
676 ghb_array_len(const GValue *gval)
678 if (gval == NULL) return 0;
679 GArray *arr = g_value_get_boxed(gval);
684 xform_string_int(const GValue *sval, GValue *ival)
688 const gchar *str = g_value_get_string(sval);
689 gint val = g_strtod(str, &end);
691 val = (guint)(~0)>>1;
692 g_value_set_int(ival, val);
696 xform_string_int64(const GValue *sval, GValue *ival)
699 const gchar *str = g_value_get_string(sval);
700 gint64 val = g_strtod(str, &end);
702 val = (guint64)(~0L)>>1;
703 g_value_set_int64(ival, val);
707 xform_string_double(const GValue *sval, GValue *dval)
709 const gchar *str = g_value_get_string(sval);
710 double val = g_strtod(str, NULL);
711 g_value_set_double(dval, val);
715 xform_boolean_double(const GValue *bval, GValue *dval)
717 gboolean b = g_value_get_boolean(bval);
719 g_value_set_double(dval, val);
723 ghb_register_transforms()
725 g_value_register_transform_func(G_TYPE_STRING, G_TYPE_INT64,
727 g_value_register_transform_func(G_TYPE_STRING, G_TYPE_INT,
729 g_value_register_transform_func(G_TYPE_STRING, G_TYPE_DOUBLE,
730 xform_string_double);
731 g_value_register_transform_func(G_TYPE_BOOLEAN, G_TYPE_DOUBLE,
732 xform_boolean_double);