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 ghb_value_int(const GValue *val)
51 if (val == NULL) return 0;
54 if (G_VALUE_TYPE(val) != G_TYPE_INT64)
56 g_value_init(&xform, G_TYPE_INT64);
57 if (!g_value_transform(val, &xform))
65 return (gint)g_value_get_int64(gval);
69 ghb_value_int64(const GValue *val)
71 if (val == NULL) return 0;
74 if (G_VALUE_TYPE(val) != G_TYPE_INT64)
76 g_value_init(&xform, G_TYPE_INT64);
77 if (!g_value_transform(val, &xform))
85 return g_value_get_int64(gval);
89 ghb_value_double(const GValue *val)
91 if (val == NULL) return 0;
94 if (G_VALUE_TYPE(val) != G_TYPE_DOUBLE)
96 g_value_init(&xform, G_TYPE_DOUBLE);
97 if (!g_value_transform(val, &xform))
105 return g_value_get_double(gval);
109 ghb_value_string(const GValue *val)
111 if (val == NULL) return 0;
114 if (G_VALUE_TYPE(val) != G_TYPE_STRING)
116 g_value_init(&xform, G_TYPE_STRING);
117 if (!g_value_transform(val, &xform))
125 return g_strdup(g_value_get_string(gval));
129 ghb_value_boolean(const GValue *val)
131 if (val == NULL) return FALSE;
134 if (G_VALUE_TYPE(val) != G_TYPE_BOOLEAN)
136 g_value_init(&xform, G_TYPE_BOOLEAN);
137 if (!g_value_transform(val, &xform))
145 return g_value_get_boolean(gval);
149 ghb_value_cmp(const GValue *vala, const GValue *valb)
154 typa = G_VALUE_TYPE(vala);
155 typb = G_VALUE_TYPE(valb);
156 if (typa == ghb_combodata_get_type()) typa = G_TYPE_STRING;
157 if (typb == ghb_combodata_get_type()) typb = G_TYPE_STRING;
163 if (typa == G_TYPE_STRING)
167 stra = ghb_value_string(vala);
168 strb = ghb_value_string(valb);
169 if (stra == NULL && strb == NULL)
181 res = strcmp(stra, strb);
186 else if (typa == G_TYPE_INT64 || typa == G_TYPE_INT ||
187 typa == G_TYPE_BOOLEAN)
189 return ghb_value_int64(vala) - ghb_value_int64(valb);
191 else if (typa == G_TYPE_DOUBLE || typa == G_TYPE_FLOAT)
193 return ghb_value_double(vala) - ghb_value_double(valb);
195 else if (typa == ghb_array_get_type())
197 // Cheating here. Just assume they are different.
198 // Maybe later I'll recurse through these
201 else if (typa == ghb_dict_get_type())
203 // Cheating here. Just assume they are different.
204 // Maybe later I'll recurse through these
209 g_warning("ghb_value_cmp: unrecognized type");
216 ghb_string_value(const gchar *str)
218 static GValue gval = {0,};
219 if (!G_IS_VALUE(&gval))
220 g_value_init(&gval, G_TYPE_STRING);
221 g_value_set_string(&gval, str);
226 ghb_int64_value(gint64 ival)
228 static GValue gval = {0,};
229 if (!G_IS_VALUE(&gval))
230 g_value_init(&gval, G_TYPE_INT64);
231 g_value_set_int64(&gval, ival);
236 ghb_int_value(gint ival)
238 static GValue gval = {0,};
239 if (!G_IS_VALUE(&gval))
240 g_value_init(&gval, G_TYPE_INT64);
241 g_value_set_int64(&gval, (gint64)ival);
246 ghb_double_value(gdouble dval)
248 static GValue gval = {0,};
249 if (!G_IS_VALUE(&gval))
250 g_value_init(&gval, G_TYPE_DOUBLE);
251 g_value_set_double(&gval, dval);
256 ghb_boolean_value(gboolean bval)
258 static GValue gval = {0,};
259 if (!G_IS_VALUE(&gval))
260 g_value_init(&gval, G_TYPE_BOOLEAN);
261 g_value_set_boolean(&gval, bval);
266 ghb_string_value_new(const gchar *str)
268 if (str == NULL) str = "";
269 GValue *gval = ghb_value_new(G_TYPE_STRING);
270 g_value_set_string(gval, str);
275 ghb_int64_value_new(gint64 ival)
277 GValue *gval = ghb_value_new(G_TYPE_INT64);
278 g_value_set_int64(gval, ival);
283 ghb_int_value_new(gint ival)
285 GValue *gval = ghb_value_new(G_TYPE_INT64);
286 g_value_set_int64(gval, ival);
291 ghb_double_value_new(gdouble dval)
293 GValue *gval = ghb_value_new(G_TYPE_DOUBLE);
294 g_value_set_double(gval, dval);
299 ghb_boolean_value_new(gboolean bval)
301 GValue *gval = ghb_value_new(G_TYPE_BOOLEAN);
302 g_value_set_boolean(gval, bval);
310 const gchar *shortOpt,
314 GValue *gval = ghb_value_new(ghb_combodata_get_type());
315 ghb_value_set_combodata(gval, index, option, shortOpt, svalue, ivalue);
323 GValue *gval = ghb_value_new(ghb_dict_get_type());
324 dict = g_hash_table_new_full(g_str_hash, g_str_equal,
325 dict_delete_key, dict_delete_value);
326 g_value_take_boxed(gval, dict);
331 ghb_array_value_new(guint size)
333 GValue *gval = ghb_value_new(ghb_array_get_type());
336 array = g_array_sized_new(FALSE, FALSE, sizeof(GValue*), size);
337 g_value_take_boxed(gval, array);
342 ghb_array_value_reset(GValue *gval, guint size)
346 array = g_array_sized_new(FALSE, FALSE, sizeof(GValue*), size);
347 g_value_take_boxed(gval, array);
351 ghb_date_value_new(GDate *date)
353 GValue *gval = ghb_value_new(g_date_get_type());
354 g_value_set_boxed(gval, date);
359 ghb_rawdata_value_new(ghb_rawdata_t *data)
361 GValue *gval = ghb_value_new(ghb_rawdata_get_type());
362 g_value_take_boxed(gval, data);
367 combodata_copy(gpointer boxed)
369 const ghb_combodata_t *combodata = (const ghb_combodata_t*)boxed;
370 ghb_combodata_t *copy = g_malloc0(sizeof(ghb_combodata_t));
371 if (combodata->option)
372 copy->option = g_strdup(combodata->option);
373 if (combodata->shortOpt)
374 copy->shortOpt = g_strdup(combodata->shortOpt);
375 if (combodata->svalue)
376 copy->svalue = g_strdup(combodata->svalue);
378 copy->index = combodata->index;
379 copy->ivalue = combodata->ivalue;
384 combodata_free(gpointer boxed)
386 ghb_combodata_t *combodata = (ghb_combodata_t*)boxed;
387 if (combodata->option)
388 g_free(combodata->option);
389 if (combodata->shortOpt)
390 g_free(combodata->shortOpt);
391 if (combodata->svalue)
392 g_free(combodata->svalue);
398 xform_combodata_to_string(const GValue *combo, GValue *sval)
400 const ghb_combodata_t *combodata = g_value_get_boxed(combo);
401 g_value_set_string(sval, combodata->shortOpt);
405 xform_combodata_to_int64(const GValue *combo, GValue *ival)
407 const ghb_combodata_t *combodata = g_value_get_boxed(combo);
408 g_value_set_int64(ival, combodata->ivalue);
412 xform_combodata_to_double(const GValue *combo, GValue *dval)
414 const ghb_combodata_t *combodata = g_value_get_boxed(combo);
415 g_value_set_double(dval, (gdouble)combodata->ivalue);
419 ghb_combodata_get_type(void)
421 static GType type_id = 0;
424 type_id = g_boxed_type_register_static(
425 g_intern_static_string("GHBCombo"),
426 (GBoxedCopyFunc) combodata_copy,
427 (GBoxedFreeFunc) combodata_free);
428 g_value_register_transform_func(type_id, G_TYPE_STRING,
429 xform_combodata_to_string);
430 g_value_register_transform_func(type_id, G_TYPE_INT64,
431 xform_combodata_to_int64);
432 g_value_register_transform_func(type_id, G_TYPE_DOUBLE,
433 xform_combodata_to_double);
439 ghb_value_set_combodata(
443 const gchar *shortOpt,
447 ghb_combodata_t combodata;
448 combodata.index = index;
449 combodata.option = g_strdup(option);
450 combodata.shortOpt = g_strdup(shortOpt);
451 combodata.svalue = g_strdup(svalue);
452 combodata.ivalue = ivalue;
453 g_value_set_boxed(gval, &combodata);
457 rawdata_copy(gpointer boxed)
459 const ghb_rawdata_t *data = (const ghb_rawdata_t*)boxed;
460 ghb_rawdata_t *copy = g_malloc(sizeof(ghb_rawdata_t));
461 copy->size = data->size;
464 copy->data = g_malloc(data->size);
465 memcpy(copy->data, data->data, data->size);
476 rawdata_free(gpointer boxed)
478 ghb_rawdata_t *data = (ghb_rawdata_t*)boxed;
479 if (data->data) g_free(data->data);
485 ghb_rawdata_get_type(void)
487 static GType type_id = 0;
489 type_id = g_boxed_type_register_static(g_intern_static_string("GHBData"),
490 (GBoxedCopyFunc) rawdata_copy,
491 (GBoxedFreeFunc) rawdata_free);
496 dict_delete_key(gpointer data)
500 g_warning("dict frees null key");
507 dict_delete_value(gpointer data)
509 GValue *gval = (GValue*)data;
512 g_warning("dict frees null value");
515 ghb_value_free(gval);
519 dict_copy(gpointer boxed)
521 GHashTable *dict = (GHashTable*)boxed;
527 copy = g_hash_table_new_full(g_str_hash, g_str_equal,
528 dict_delete_key, dict_delete_value);
530 g_hash_table_iter_init(&iter, dict);
531 // middle (void*) cast prevents gcc warning "defreferencing type-punned
532 // pointer will break strict-aliasing rules"
533 while (g_hash_table_iter_next(
534 &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&gval))
536 g_hash_table_insert(copy, g_strdup(key), ghb_value_dup(gval));
542 dict_free(gpointer boxed)
544 GHashTable *dict = (GHashTable*)boxed;
545 g_hash_table_destroy(dict);
550 ghb_dict_get_type(void)
552 static GType type_id = 0;
554 type_id = g_boxed_type_register_static(
555 g_intern_static_string("GHBDict"),
556 (GBoxedCopyFunc) dict_copy,
557 (GBoxedFreeFunc) dict_free);
562 ghb_dict_insert(GValue *gval, gchar *key, GValue *val)
564 GHashTable *dict = g_value_get_boxed(gval);
565 g_hash_table_insert(dict, key, val);
569 ghb_dict_iter_init(GHashTableIter *iter, GValue *gval)
571 GHashTable *dict = g_value_get_boxed(gval);
572 g_hash_table_iter_init(iter, dict);
576 ghb_dict_lookup(GValue *gval, const gchar *key)
578 GHashTable *dict = g_value_get_boxed(gval);
579 return g_hash_table_lookup(dict, key);
583 ghb_dict_remove(GValue *gval, const gchar *key)
585 GHashTable *dict = g_value_get_boxed(gval);
586 return g_hash_table_remove(dict, key);
590 array_copy(gpointer boxed)
592 const GArray *array = (const GArray*)boxed;
593 GArray *copy = g_array_new(FALSE, FALSE, sizeof(GValue*));
595 GValue *gval, *gval_copy;
598 for (ii = 0; ii < array->len; ii++)
600 gval = g_array_index(array, GValue*, ii);
603 gval_copy = ghb_value_dup(gval);
604 g_array_append_val(copy, gval_copy);
611 array_free(gpointer boxed)
613 GArray *array = (GArray*)boxed;
617 for (ii = 0; ii < array->len; ii++)
619 gval = g_array_index(array, GValue*, ii);
622 ghb_value_free(gval);
625 g_array_free(array, TRUE);
630 ghb_array_get_type(void)
632 static GType type_id = 0;
634 type_id = g_boxed_type_register_static(
635 g_intern_static_string("GHBArray"),
636 (GBoxedCopyFunc) array_copy,
637 (GBoxedFreeFunc) array_free);
642 ghb_array_get_nth(const GValue *gval, gint ii)
644 GArray *arr = g_value_get_boxed(gval);
645 return g_array_index(arr, GValue*, ii);
649 ghb_array_append(GValue *gval, GValue *val)
651 GArray *arr = g_value_get_boxed(gval);
652 // A little nastyness here. The array pointer
653 // can change when the array changes size. So
654 // I must re-box it in the GValue each time.
655 arr = g_array_append_val(arr, val);
656 memset(gval, 0, sizeof(GValue));
657 g_value_init(gval, ghb_array_get_type());
658 g_value_take_boxed(gval, arr);
662 ghb_array_remove(GValue *gval, guint ii)
664 GArray *arr = g_value_get_boxed(gval);
665 // A little nastyness here. The array pointer
666 // can change when the array changes size. So
667 // I must re-box it in the GValue each time.
668 arr = g_array_remove_index(arr, ii);
669 memset(gval, 0, sizeof(GValue));
670 g_value_init(gval, ghb_array_get_type());
671 g_value_take_boxed(gval, arr);
675 ghb_array_len(const GValue *gval)
677 if (gval == NULL) return 0;
678 GArray *arr = g_value_get_boxed(gval);