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_BOOLEAN)
68 else if (tp == ghb_array_get_type())
72 else if (tp == ghb_dict_get_type())
80 ghb_value_int(const GValue *val)
84 if (val == NULL) return 0;
86 if (G_VALUE_TYPE(val) != G_TYPE_INT64)
88 g_value_init(&xform, G_TYPE_INT64);
89 if (!g_value_transform(val, &xform))
91 debug_show_type(G_VALUE_TYPE(val));
92 g_warning("int can't transform");
95 result = (gint)g_value_get_int64(&xform);
96 g_value_unset(&xform);
100 result = (gint)g_value_get_int64(val);
106 ghb_value_int64(const GValue *val)
110 if (val == NULL) return 0;
112 if (G_VALUE_TYPE(val) != G_TYPE_INT64)
114 g_value_init(&xform, G_TYPE_INT64);
115 if (!g_value_transform(val, &xform))
117 debug_show_type(G_VALUE_TYPE(val));
118 g_warning("int64 can't transform");
121 result = g_value_get_int64(&xform);
122 g_value_unset(&xform);
126 result = g_value_get_int64(val);
132 ghb_value_double(const GValue *val)
136 if (val == NULL) return 0;
138 if (G_VALUE_TYPE(val) != G_TYPE_DOUBLE)
140 g_value_init(&xform, G_TYPE_DOUBLE);
141 if (!g_value_transform(val, &xform))
143 debug_show_type(G_VALUE_TYPE(val));
144 g_warning("double can't transform");
147 result = g_value_get_double(&xform);
148 g_value_unset(&xform);
152 result = g_value_get_double(val);
158 ghb_value_string(const GValue *val)
162 if (val == NULL) return 0;
164 if (G_VALUE_TYPE(val) != G_TYPE_STRING)
166 g_value_init(&xform, G_TYPE_STRING);
167 if (!g_value_transform(val, &xform))
169 debug_show_type(G_VALUE_TYPE(val));
170 g_warning("string can't transform");
173 result = g_strdup(g_value_get_string(&xform));
174 g_value_unset(&xform);
178 result = g_strdup(g_value_get_string(val));
184 ghb_value_boolean(const GValue *val)
188 if (val == NULL) return FALSE;
190 if (G_VALUE_TYPE(val) != G_TYPE_BOOLEAN)
192 g_value_init(&xform, G_TYPE_BOOLEAN);
193 if (!g_value_transform(val, &xform))
195 debug_show_type(G_VALUE_TYPE(val));
196 g_warning("boolean can't transform");
199 result = g_value_get_boolean(&xform);
200 g_value_unset(&xform);
204 result = g_value_get_boolean(val);
210 ghb_value_cmp(const GValue *vala, const GValue *valb)
215 typa = G_VALUE_TYPE(vala);
216 typb = G_VALUE_TYPE(valb);
222 if (typa == G_TYPE_STRING)
226 stra = ghb_value_string(vala);
227 strb = ghb_value_string(valb);
228 if (stra == NULL && strb == NULL)
240 res = strcmp(stra, strb);
245 else if (typa == G_TYPE_INT64 || typa == G_TYPE_INT ||
246 typa == G_TYPE_BOOLEAN)
248 return ghb_value_int64(vala) - ghb_value_int64(valb);
250 else if (typa == G_TYPE_DOUBLE || typa == G_TYPE_FLOAT)
252 return ghb_value_double(vala) - ghb_value_double(valb);
254 else if (typa == ghb_array_get_type())
256 // Cheating here. Just assume they are different.
257 // Maybe later I'll recurse through these
260 else if (typa == ghb_dict_get_type())
262 // Cheating here. Just assume they are different.
263 // Maybe later I'll recurse through these
268 g_warning("ghb_value_cmp: unrecognized type");
275 ghb_string_value(const gchar *str)
277 static GValue gval = {0,};
278 if (!G_IS_VALUE(&gval))
279 g_value_init(&gval, G_TYPE_STRING);
280 g_value_set_string(&gval, str);
285 ghb_int64_value(gint64 ival)
287 static GValue gval = {0,};
288 if (!G_IS_VALUE(&gval))
289 g_value_init(&gval, G_TYPE_INT64);
290 g_value_set_int64(&gval, ival);
295 ghb_int_value(gint ival)
297 static GValue gval = {0,};
298 if (!G_IS_VALUE(&gval))
299 g_value_init(&gval, G_TYPE_INT64);
300 g_value_set_int64(&gval, (gint64)ival);
305 ghb_double_value(gdouble dval)
307 static GValue gval = {0,};
308 if (!G_IS_VALUE(&gval))
309 g_value_init(&gval, G_TYPE_DOUBLE);
310 g_value_set_double(&gval, dval);
315 ghb_boolean_value(gboolean bval)
317 static GValue gval = {0,};
318 if (!G_IS_VALUE(&gval))
319 g_value_init(&gval, G_TYPE_BOOLEAN);
320 g_value_set_boolean(&gval, bval);
325 ghb_string_value_new(const gchar *str)
327 if (str == NULL) str = "";
328 GValue *gval = ghb_value_new(G_TYPE_STRING);
329 g_value_set_string(gval, str);
334 ghb_int64_value_new(gint64 ival)
336 GValue *gval = ghb_value_new(G_TYPE_INT64);
337 g_value_set_int64(gval, ival);
342 ghb_int_value_new(gint ival)
344 GValue *gval = ghb_value_new(G_TYPE_INT64);
345 g_value_set_int64(gval, ival);
350 ghb_double_value_new(gdouble dval)
352 GValue *gval = ghb_value_new(G_TYPE_DOUBLE);
353 g_value_set_double(gval, dval);
358 ghb_boolean_value_new(gboolean bval)
360 GValue *gval = ghb_value_new(G_TYPE_BOOLEAN);
361 g_value_set_boolean(gval, bval);
369 GValue *gval = ghb_value_new(ghb_dict_get_type());
370 dict = g_hash_table_new_full(g_str_hash, g_str_equal,
371 dict_delete_key, dict_delete_value);
372 g_value_take_boxed(gval, dict);
377 ghb_array_value_new(guint size)
379 GValue *gval = ghb_value_new(ghb_array_get_type());
382 array = g_array_sized_new(FALSE, FALSE, sizeof(GValue*), size);
383 g_value_take_boxed(gval, array);
388 ghb_array_value_reset(GValue *gval, guint size)
392 array = g_array_sized_new(FALSE, FALSE, sizeof(GValue*), size);
393 g_value_take_boxed(gval, array);
397 ghb_date_value_new(GDate *date)
399 GValue *gval = ghb_value_new(g_date_get_type());
400 g_value_set_boxed(gval, date);
405 ghb_rawdata_value_new(ghb_rawdata_t *data)
407 GValue *gval = ghb_value_new(ghb_rawdata_get_type());
408 g_value_take_boxed(gval, data);
413 rawdata_copy(gpointer boxed)
415 const ghb_rawdata_t *data = (const ghb_rawdata_t*)boxed;
416 ghb_rawdata_t *copy = g_malloc(sizeof(ghb_rawdata_t));
417 copy->size = data->size;
420 copy->data = g_malloc(data->size);
421 memcpy(copy->data, data->data, data->size);
432 rawdata_free(gpointer boxed)
434 ghb_rawdata_t *data = (ghb_rawdata_t*)boxed;
435 if (data->data) g_free(data->data);
441 ghb_rawdata_get_type(void)
443 static GType type_id = 0;
445 type_id = g_boxed_type_register_static(g_intern_static_string("GHBData"),
446 (GBoxedCopyFunc) rawdata_copy,
447 (GBoxedFreeFunc) rawdata_free);
452 dict_delete_key(gpointer data)
456 g_warning("dict frees null key");
463 dict_delete_value(gpointer data)
465 GValue *gval = (GValue*)data;
468 g_warning("dict frees null value");
471 ghb_value_free(gval);
475 dict_copy(gpointer boxed)
477 GHashTable *dict = (GHashTable*)boxed;
483 copy = g_hash_table_new_full(g_str_hash, g_str_equal,
484 dict_delete_key, dict_delete_value);
486 g_hash_table_iter_init(&iter, dict);
487 // middle (void*) cast prevents gcc warning "defreferencing type-punned
488 // pointer will break strict-aliasing rules"
489 while (g_hash_table_iter_next(
490 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
492 g_hash_table_insert(copy, g_strdup(key), ghb_value_dup(gval));
498 dict_free(gpointer boxed)
500 GHashTable *dict = (GHashTable*)boxed;
501 g_hash_table_destroy(dict);
506 ghb_dict_get_type(void)
508 static GType type_id = 0;
510 type_id = g_boxed_type_register_static(
511 g_intern_static_string("GHBDict"),
512 (GBoxedCopyFunc) dict_copy,
513 (GBoxedFreeFunc) dict_free);
518 ghb_dict_insert(GValue *gval, gchar *key, GValue *val)
520 GHashTable *dict = g_value_get_boxed(gval);
521 g_hash_table_insert(dict, key, val);
525 ghb_dict_iter_init(GHashTableIter *iter, GValue *gval)
527 GHashTable *dict = g_value_get_boxed(gval);
528 g_hash_table_iter_init(iter, dict);
532 ghb_dict_lookup(GValue *gval, const gchar *key)
534 GHashTable *dict = g_value_get_boxed(gval);
535 return g_hash_table_lookup(dict, key);
539 ghb_dict_remove(GValue *gval, const gchar *key)
541 GHashTable *dict = g_value_get_boxed(gval);
542 return g_hash_table_remove(dict, key);
546 array_copy(gpointer boxed)
548 const GArray *array = (const GArray*)boxed;
549 GArray *copy = g_array_new(FALSE, FALSE, sizeof(GValue*));
551 GValue *gval, *gval_copy;
554 for (ii = 0; ii < array->len; ii++)
556 gval = g_array_index(array, GValue*, ii);
559 gval_copy = ghb_value_dup(gval);
560 g_array_append_val(copy, gval_copy);
567 array_free(gpointer boxed)
569 GArray *array = (GArray*)boxed;
573 for (ii = 0; ii < array->len; ii++)
575 gval = g_array_index(array, GValue*, ii);
578 ghb_value_free(gval);
581 g_array_free(array, TRUE);
586 ghb_array_get_type(void)
588 static GType type_id = 0;
590 type_id = g_boxed_type_register_static(
591 g_intern_static_string("GHBArray"),
592 (GBoxedCopyFunc) array_copy,
593 (GBoxedFreeFunc) array_free);
598 ghb_array_get_nth(const GValue *gval, gint ii)
600 GArray *arr = g_value_get_boxed(gval);
601 return g_array_index(arr, GValue*, ii);
605 ghb_array_insert(GValue *gval, guint ii, GValue *val)
607 GArray *arr = g_value_get_boxed(gval);
608 // A little nastyness here. The array pointer
609 // can change when the array changes size. So
610 // I must re-box it in the GValue each time.
611 arr = g_array_insert_val(arr, ii, val);
612 memset(gval, 0, sizeof(GValue));
613 g_value_init(gval, ghb_array_get_type());
614 g_value_take_boxed(gval, arr);
618 ghb_array_append(GValue *gval, GValue *val)
620 GArray *arr = g_value_get_boxed(gval);
621 // A little nastyness here. The array pointer
622 // can change when the array changes size. So
623 // I must re-box it in the GValue each time.
624 arr = g_array_append_val(arr, val);
625 memset(gval, 0, sizeof(GValue));
626 g_value_init(gval, ghb_array_get_type());
627 g_value_take_boxed(gval, arr);
631 ghb_array_remove(GValue *gval, guint ii)
633 GArray *arr = g_value_get_boxed(gval);
634 // A little nastyness here. The array pointer
635 // can change when the array changes size. So
636 // I must re-box it in the GValue each time.
637 arr = g_array_remove_index(arr, ii);
638 memset(gval, 0, sizeof(GValue));
639 g_value_init(gval, ghb_array_get_type());
640 g_value_take_boxed(gval, arr);
644 ghb_array_len(const GValue *gval)
646 if (gval == NULL) return 0;
647 GArray *arr = g_value_get_boxed(gval);
652 xform_string_int(const GValue *sval, GValue *ival)
654 const gchar *str = g_value_get_string(sval);
655 gint val = g_strtod(str, NULL);
656 g_value_set_int(ival, val);
660 xform_string_int64(const GValue *sval, GValue *ival)
662 const gchar *str = g_value_get_string(sval);
663 gint64 val = g_strtod(str, NULL);
664 g_value_set_int64(ival, val);
668 xform_string_double(const GValue *sval, GValue *dval)
670 const gchar *str = g_value_get_string(sval);
671 double val = g_strtod(str, NULL);
672 g_value_set_double(dval, val);
676 xform_boolean_double(const GValue *bval, GValue *dval)
678 gboolean b = g_value_get_boolean(bval);
680 g_value_set_double(dval, val);
684 ghb_register_transforms()
686 g_value_register_transform_func(G_TYPE_STRING, G_TYPE_INT64,
688 g_value_register_transform_func(G_TYPE_STRING, G_TYPE_INT,
690 g_value_register_transform_func(G_TYPE_STRING, G_TYPE_DOUBLE,
691 xform_string_double);
692 g_value_register_transform_func(G_TYPE_BOOLEAN, G_TYPE_DOUBLE,
693 xform_boolean_double);