1 /* GConf
2 * Copyright (C) 1999, 2000, 2002 Red Hat Inc.
3 *
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.
8 *
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.
13 *
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., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include <config.h>
21 #include "gconf-value.h"
22 #include "gconf-error.h"
23 #include "gconf-schema.h"
24 #include "gconf-internals.h"
25 #include <errno.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 typedef struct {
30 GConfValueType type;
31 union {
32 gchar* string_data;
33 gint int_data;
34 gboolean bool_data;
35 gdouble float_data;
36 GConfSchema* schema_data;
37 struct {
38 GConfValueType type;
39 GSList* list;
40 } list_data;
41 struct {
42 GConfValue* car;
43 GConfValue* cdr;
44 } pair_data;
45 } d;
46 } GConfRealValue;
47
48 #define REAL_VALUE(x) ((GConfRealValue*)(x))
49
50 static void
set_string(gchar ** dest,const gchar * src)51 set_string(gchar** dest, const gchar* src)
52 {
53 g_free(*dest);
54 *dest = g_strdup(src);
55 }
56
57 /*
58 * Values
59 */
60
61 GConfValue*
gconf_value_new(GConfValueType type)62 gconf_value_new(GConfValueType type)
63 {
64 GConfValue* value;
65 static gboolean initted = FALSE;
66
67 g_return_val_if_fail(GCONF_VALUE_TYPE_VALID(type), NULL);
68
69 if (!initted)
70 {
71 _gconf_init_i18n ();
72 initted = TRUE;
73 }
74
75 value = (GConfValue*) g_slice_new0 (GConfRealValue);
76
77 value->type = type;
78
79 /* the g_new0() is important: sets list type to invalid, NULLs all
80 * pointers
81 */
82
83 return value;
84 }
85
86 GConfValue*
gconf_value_new_from_string(GConfValueType type,const gchar * value_str,GError ** err)87 gconf_value_new_from_string(GConfValueType type, const gchar* value_str,
88 GError** err)
89 {
90 GConfValue* value;
91
92 g_return_val_if_fail (type != GCONF_VALUE_LIST, NULL);
93 g_return_val_if_fail (type != GCONF_VALUE_PAIR, NULL);
94
95 value = gconf_value_new(type);
96
97 switch (type)
98 {
99 case GCONF_VALUE_INT:
100 {
101 char* endptr = NULL;
102 glong result;
103
104 errno = 0;
105 result = strtol(value_str, &endptr, 10);
106
107 if (endptr == value_str)
108 {
109 if (err)
110 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
111 _("Didn't understand `%s' (expected integer)"),
112 value_str);
113
114 gconf_value_free(value);
115 value = NULL;
116 }
117 else if (errno == ERANGE)
118 {
119 if (err)
120 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
121 _("Integer `%s' is too large or small"),
122 value_str);
123 gconf_value_free(value);
124 value = NULL;
125 }
126 else
127 gconf_value_set_int(value, result);
128 }
129 break;
130 case GCONF_VALUE_FLOAT:
131 {
132 double num;
133
134 if (gconf_string_to_double(value_str, &num))
135 {
136 gconf_value_set_float(value, num);
137 }
138 else
139 {
140 if (err)
141 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
142 _("Didn't understand `%s' (expected real number)"),
143 value_str);
144
145 gconf_value_free(value);
146 value = NULL;
147 }
148 }
149 break;
150 case GCONF_VALUE_STRING:
151 if (!g_utf8_validate (value_str, -1, NULL))
152 {
153 g_set_error (err, GCONF_ERROR,
154 GCONF_ERROR_PARSE_ERROR,
155 _("Text contains invalid UTF-8"));
156 gconf_value_free(value);
157 value = NULL;
158 }
159 else
160 {
161 gconf_value_set_string(value, value_str);
162 }
163 break;
164 case GCONF_VALUE_BOOL:
165 switch (*value_str)
166 {
167 case 't':
168 case 'T':
169 case '1':
170 case 'y':
171 case 'Y':
172 gconf_value_set_bool(value, TRUE);
173 break;
174
175 case 'f':
176 case 'F':
177 case '0':
178 case 'n':
179 case 'N':
180 gconf_value_set_bool(value, FALSE);
181 break;
182
183 default:
184 if (err)
185 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
186 _("Didn't understand `%s' (expected true or false)"),
187 value_str);
188
189 gconf_value_free(value);
190 value = NULL;
191 break;
192 }
193 break;
194 case GCONF_VALUE_LIST:
195 case GCONF_VALUE_PAIR:
196 default:
197 g_assert_not_reached();
198 break;
199 }
200
201 return value;
202 }
203
204 static char *
escape_string(const char * str,const char * escaped_chars)205 escape_string(const char *str, const char *escaped_chars)
206 {
207 gint i, j, len;
208 gchar* ret;
209
210 len = 0;
211 for (i = 0; str[i] != '\0'; i++)
212 {
213 if (strchr(escaped_chars, str[i]) != NULL ||
214 str[i] == '\\')
215 len++;
216 len++;
217 }
218
219 ret = g_malloc(len + 1);
220
221 j = 0;
222 for (i = 0; str[i] != '\0'; i++)
223 {
224 if (strchr(escaped_chars, str[i]) != NULL ||
225 str[i] == '\\')
226 {
227 ret[j++] = '\\';
228 }
229 ret[j++] = str[i];
230 }
231 ret[j++] = '\0';
232
233 return ret;
234 }
235
236 GConfValue*
gconf_value_new_list_from_string(GConfValueType list_type,const gchar * str,GError ** err)237 gconf_value_new_list_from_string(GConfValueType list_type,
238 const gchar* str,
239 GError** err)
240 {
241 int i, len;
242 gboolean escaped, pending_chars;
243 GString *string;
244 GConfValue* value;
245 GSList *list;
246
247 g_return_val_if_fail(list_type != GCONF_VALUE_LIST, NULL);
248 g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, NULL);
249
250 if (!g_utf8_validate (str, -1, NULL))
251 {
252 g_set_error (err, GCONF_ERROR,
253 GCONF_ERROR_PARSE_ERROR,
254 _("Text contains invalid UTF-8"));
255 return NULL;
256 }
257
258 if (str[0] != '[')
259 {
260 if (err)
261 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
262 _("Didn't understand `%s' (list must start with a '[')"),
263 str);
264 return NULL;
265 }
266
267 len = strlen(str);
268
269 /* Note: by now len is sure to be 1 or larger, so len-1 will never be
270 * negative */
271 if (str[len-1] != ']')
272 {
273 if (err)
274 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
275 _("Didn't understand `%s' (list must end with a ']')"),
276 str);
277 return NULL;
278 }
279
280 if (strstr(str, "[]"))
281 {
282 value = gconf_value_new(GCONF_VALUE_LIST);
283 gconf_value_set_list_type(value, list_type);
284
285 return value;
286 }
287
288 escaped = FALSE;
289 pending_chars = FALSE;
290 list = NULL;
291 string = g_string_new(NULL);
292
293 for (i = 1; str[i] != '\0'; i++)
294 {
295 if ( ! escaped &&
296 (str[i] == ',' ||
297 str[i] == ']'))
298 {
299 GConfValue* val;
300 val = gconf_value_new_from_string(list_type, string->str, err);
301
302 if (err && *err != NULL)
303 {
304 /* Free values so far */
305 g_slist_foreach(list, (GFunc)gconf_value_free, NULL);
306 g_slist_free(list);
307
308 g_string_free(string, TRUE);
309
310 return NULL;
311 }
312
313 g_string_assign(string, "");
314 list = g_slist_prepend(list, val);
315 if (str[i] == ']' &&
316 i != len-1)
317 {
318 /* Free values so far */
319 g_slist_foreach(list, (GFunc)gconf_value_free, NULL);
320 g_slist_free(list);
321
322 g_string_free(string, TRUE);
323
324 if (err)
325 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
326 _("Didn't understand `%s' (extra unescaped ']' found inside list)"),
327 str);
328 return NULL;
329 }
330 pending_chars = FALSE;
331 }
332 else if ( ! escaped && str[i] == '\\')
333 {
334 escaped = TRUE;
335 pending_chars = TRUE;
336 }
337 else
338 {
339 g_string_append_c(string, str[i]);
340 escaped = FALSE;
341 pending_chars = TRUE;
342 }
343 }
344
345 g_string_free(string, TRUE);
346
347 if (pending_chars)
348 {
349 /* Free values so far */
350 g_slist_foreach(list, (GFunc)gconf_value_free, NULL);
351 g_slist_free(list);
352
353 g_string_free(string, TRUE);
354
355 if (err)
356 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
357 _("Didn't understand `%s' (extra trailing characters)"),
358 str);
359 return NULL;
360 }
361
362 /* inverse list as we were prepending to it */
363 list = g_slist_reverse(list);
364
365 value = gconf_value_new(GCONF_VALUE_LIST);
366 gconf_value_set_list_type(value, list_type);
367
368 gconf_value_set_list_nocopy(value, list);
369
370 return value;
371 }
372
373 GConfValue*
gconf_value_new_pair_from_string(GConfValueType car_type,GConfValueType cdr_type,const gchar * str,GError ** err)374 gconf_value_new_pair_from_string(GConfValueType car_type,
375 GConfValueType cdr_type,
376 const gchar* str,
377 GError** err)
378 {
379 int i, len;
380 int elem;
381 gboolean escaped, pending_chars;
382 GString *string;
383 GConfValue* value;
384 GConfValue* car;
385 GConfValue* cdr;
386
387 g_return_val_if_fail(car_type != GCONF_VALUE_LIST, NULL);
388 g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, NULL);
389 g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, NULL);
390 g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, NULL);
391
392 if (!g_utf8_validate (str, -1, NULL))
393 {
394 g_set_error (err, GCONF_ERROR,
395 GCONF_ERROR_PARSE_ERROR,
396 _("Text contains invalid UTF-8"));
397 return NULL;
398 }
399
400 if (str[0] != '(')
401 {
402 if (err)
403 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
404 _("Didn't understand `%s' (pair must start with a '(')"),
405 str);
406 return NULL;
407 }
408
409 len = strlen(str);
410
411 /* Note: by now len is sure to be 1 or larger, so len-1 will never be
412 * negative */
413 if (str[len-1] != ')')
414 {
415 if (err)
416 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
417 _("Didn't understand `%s' (pair must end with a ')')"),
418 str);
419 return NULL;
420 }
421
422 escaped = FALSE;
423 pending_chars = FALSE;
424 car = cdr = NULL;
425 string = g_string_new(NULL);
426 elem = 0;
427
428 for (i = 1; str[i] != '\0'; i++)
429 {
430 if ( ! escaped &&
431 (str[i] == ',' ||
432 str[i] == ')'))
433 {
434 if ((str[i] == ')' && elem != 1) ||
435 (elem > 1))
436 {
437 /* Free values so far */
438 if (car)
439 gconf_value_free(car);
440 if (cdr)
441 gconf_value_free(cdr);
442
443 g_string_free(string, TRUE);
444
445 if (err)
446 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
447 _("Didn't understand `%s' (wrong number of elements)"),
448 str);
449 return NULL;
450 }
451
452 if (elem == 0)
453 car = gconf_value_new_from_string(car_type, string->str, err);
454 else if (elem == 1)
455 cdr = gconf_value_new_from_string(cdr_type, string->str, err);
456
457 elem ++;
458
459 if (err && *err != NULL)
460 {
461 /* Free values so far */
462 if (car)
463 gconf_value_free(car);
464 if (cdr)
465 gconf_value_free(cdr);
466
467 g_string_free(string, TRUE);
468
469 return NULL;
470 }
471
472 g_string_assign(string, "");
473
474 if (str[i] == ')' &&
475 i != len-1)
476 {
477 /* Free values so far */
478 if (car)
479 gconf_value_free(car);
480 if (cdr)
481 gconf_value_free(cdr);
482
483 g_string_free(string, TRUE);
484
485 if (err)
486 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
487 _("Didn't understand `%s' (extra unescaped ')' found inside pair)"),
488 str);
489 return NULL;
490 }
491 pending_chars = FALSE;
492 }
493 else if ( ! escaped && str[i] == '\\')
494 {
495 escaped = TRUE;
496 pending_chars = TRUE;
497 }
498 else
499 {
500 g_string_append_c(string, str[i]);
501 escaped = FALSE;
502 pending_chars = TRUE;
503 }
504 }
505
506 g_string_free(string, TRUE);
507
508 if (pending_chars)
509 {
510 /* Free values so far */
511 if (car)
512 gconf_value_free(car);
513 if (cdr)
514 gconf_value_free(cdr);
515
516 if (err)
517 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
518 _("Didn't understand `%s' (extra trailing characters)"),
519 str);
520 return NULL;
521 }
522
523 if (elem != 2)
524 {
525 /* Free values so far */
526 if (car)
527 gconf_value_free(car);
528 if (cdr)
529 gconf_value_free(cdr);
530
531 if (err)
532 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
533 _("Didn't understand `%s' (wrong number of elements)"),
534 str);
535 return NULL;
536 }
537
538 value = gconf_value_new(GCONF_VALUE_PAIR);
539 gconf_value_set_car_nocopy(value, car);
540 gconf_value_set_cdr_nocopy(value, cdr);
541
542 return value;
543 }
544
545 gchar*
gconf_value_to_string(const GConfValue * value)546 gconf_value_to_string(const GConfValue* value)
547 {
548 /* These strings shouldn't be translated; they're primarily
549 intended for machines to read, not humans, though I do
550 use them in some debug spew
551 */
552 gchar* retval = NULL;
553
554 switch (value->type)
555 {
556 case GCONF_VALUE_INT:
557 retval = g_strdup_printf("%d", gconf_value_get_int(value));
558 break;
559 case GCONF_VALUE_FLOAT:
560 retval = gconf_double_to_string(gconf_value_get_float(value));
561 break;
562 case GCONF_VALUE_STRING:
563 retval = g_strdup(gconf_value_get_string(value));
564 break;
565 case GCONF_VALUE_BOOL:
566 retval = gconf_value_get_bool(value) ? g_strdup("true") : g_strdup("false");
567 break;
568 case GCONF_VALUE_LIST:
569 {
570 GSList* list;
571
572 list = gconf_value_get_list(value);
573
574 if (list == NULL)
575 retval = g_strdup("[]");
576 else
577 {
578 gchar* buf = NULL;
579 guint bufsize = 64;
580 guint cur = 0;
581
582 g_assert(list != NULL);
583
584 buf = g_malloc(bufsize+3); /* my +3 superstition */
585
586 buf[0] = '[';
587 ++cur;
588
589 g_assert(cur < bufsize);
590
591 while (list != NULL)
592 {
593 gchar* tmp;
594 gchar* elem;
595 guint len;
596
597 tmp = gconf_value_to_string((GConfValue*)list->data);
598
599 g_assert(tmp != NULL);
600
601 elem = escape_string(tmp, ",]");
602
603 g_free(tmp);
604
605 len = strlen(elem);
606
607 if ((cur + len + 2) >= bufsize) /* +2 for '\0' and comma */
608 {
609 bufsize = MAX(bufsize*2, bufsize+len+4);
610 buf = g_realloc(buf, bufsize+3);
611 }
612
613 g_assert(cur < bufsize);
614
615 strcpy(&buf[cur], elem);
616 cur += len;
617
618 g_assert(cur < bufsize);
619
620 g_free(elem);
621
622 buf[cur] = ',';
623 ++cur;
624
625 g_assert(cur < bufsize);
626
627 list = g_slist_next(list);
628 }
629
630 g_assert(cur < bufsize);
631
632 buf[cur-1] = ']'; /* overwrites last comma */
633 buf[cur] = '\0';
634
635 retval = buf;
636 }
637 }
638 break;
639 case GCONF_VALUE_PAIR:
640 {
641 gchar* tmp;
642 gchar* car;
643 gchar* cdr;
644
645 if (gconf_value_get_car (value))
646 tmp = gconf_value_to_string(gconf_value_get_car(value));
647 else
648 tmp = g_strdup ("nil");
649 car = escape_string(tmp, ",)");
650 g_free(tmp);
651
652 if (gconf_value_get_cdr (value))
653 tmp = gconf_value_to_string(gconf_value_get_cdr(value));
654 else
655 tmp = g_strdup ("nil");
656 cdr = escape_string(tmp, ",)");
657 g_free(tmp);
658 retval = g_strdup_printf("(%s,%s)", car, cdr);
659 g_free(car);
660 g_free(cdr);
661 }
662 break;
663 /* These remaining shouldn't really be used outside of debug spew... */
664 case GCONF_VALUE_INVALID:
665 retval = g_strdup("Invalid");
666 break;
667 case GCONF_VALUE_SCHEMA:
668 {
669 const gchar* locale;
670 const gchar* type;
671 const gchar* list_type;
672 const gchar* car_type;
673 const gchar* cdr_type;
674
675 locale = gconf_schema_get_locale(gconf_value_get_schema(value));
676 type = gconf_value_type_to_string(gconf_schema_get_type(gconf_value_get_schema(value)));
677 list_type = gconf_value_type_to_string(gconf_schema_get_list_type(gconf_value_get_schema(value)));
678 car_type = gconf_value_type_to_string(gconf_schema_get_car_type(gconf_value_get_schema(value)));
679 cdr_type = gconf_value_type_to_string(gconf_schema_get_cdr_type(gconf_value_get_schema(value)));
680
681 retval = g_strdup_printf("Schema (type: `%s' list_type: '%s' "
682 "car_type: '%s' cdr_type: '%s' locale: `%s')",
683 type, list_type, car_type, cdr_type,
684 locale ? locale : "(null)");
685 }
686 break;
687 default:
688 g_assert_not_reached();
689 break;
690 }
691
692 return retval;
693 }
694
695 static GSList*
copy_value_list(GSList * list)696 copy_value_list(GSList* list)
697 {
698 GSList* copy = NULL;
699 GSList* tmp = list;
700
701 while (tmp != NULL)
702 {
703 copy = g_slist_prepend(copy, gconf_value_copy(tmp->data));
704
705 tmp = g_slist_next(tmp);
706 }
707
708 copy = g_slist_reverse(copy);
709
710 return copy;
711 }
712
713 GType
gconf_value_get_type()714 gconf_value_get_type ()
715 {
716 static GType type = 0;
717
718 if (type == 0)
719 type = g_boxed_type_register_static (g_intern_static_string ("GConfValue"),
720 (GBoxedCopyFunc) gconf_value_copy,
721 (GBoxedFreeFunc) gconf_value_free);
722 return type;
723 }
724
725 GConfValue*
gconf_value_copy(const GConfValue * src)726 gconf_value_copy (const GConfValue* src)
727 {
728 GConfRealValue *dest;
729 GConfRealValue *real;
730
731 g_return_val_if_fail(src != NULL, NULL);
732
733 real = REAL_VALUE (src);
734 dest = REAL_VALUE (gconf_value_new (src->type));
735
736 switch (real->type)
737 {
738 case GCONF_VALUE_INT:
739 case GCONF_VALUE_FLOAT:
740 case GCONF_VALUE_BOOL:
741 case GCONF_VALUE_INVALID:
742 dest->d = real->d;
743 break;
744 case GCONF_VALUE_STRING:
745 set_string(&dest->d.string_data, real->d.string_data);
746 break;
747 case GCONF_VALUE_SCHEMA:
748 if (real->d.schema_data)
749 dest->d.schema_data = gconf_schema_copy(real->d.schema_data);
750 else
751 dest->d.schema_data = NULL;
752 break;
753
754 case GCONF_VALUE_LIST:
755 {
756 GSList* copy;
757
758 copy = copy_value_list(real->d.list_data.list);
759
760 dest->d.list_data.list = copy;
761 dest->d.list_data.type = real->d.list_data.type;
762 }
763 break;
764
765 case GCONF_VALUE_PAIR:
766
767 if (real->d.pair_data.car)
768 dest->d.pair_data.car = gconf_value_copy(real->d.pair_data.car);
769 else
770 dest->d.pair_data.car = NULL;
771
772 if (real->d.pair_data.cdr)
773 dest->d.pair_data.cdr = gconf_value_copy(real->d.pair_data.cdr);
774 else
775 dest->d.pair_data.cdr = NULL;
776
777 break;
778
779 default:
780 g_assert_not_reached();
781 }
782
783 return (GConfValue*) dest;
784 }
785
786 static void
gconf_value_free_list(GConfValue * value)787 gconf_value_free_list(GConfValue* value)
788 {
789 GSList* tmp;
790 GConfRealValue *real;
791
792 g_return_if_fail(value != NULL);
793 g_return_if_fail(value->type == GCONF_VALUE_LIST);
794
795 real = REAL_VALUE (value);
796
797 tmp = real->d.list_data.list;
798
799 while (tmp != NULL)
800 {
801 gconf_value_free(tmp->data);
802
803 tmp = g_slist_next(tmp);
804 }
805 g_slist_free(real->d.list_data.list);
806
807 real->d.list_data.list = NULL;
808 }
809
810 void
gconf_value_free(GConfValue * value)811 gconf_value_free(GConfValue* value)
812 {
813 GConfRealValue *real;
814
815 g_return_if_fail(value != NULL);
816
817 real = REAL_VALUE (value);
818
819 switch (real->type)
820 {
821 case GCONF_VALUE_STRING:
822 g_free(real->d.string_data);
823 break;
824 case GCONF_VALUE_SCHEMA:
825 if (real->d.schema_data != NULL)
826 gconf_schema_free(real->d.schema_data);
827 break;
828 case GCONF_VALUE_LIST:
829 gconf_value_free_list(value);
830 break;
831 case GCONF_VALUE_PAIR:
832 if (real->d.pair_data.car != NULL)
833 gconf_value_free(real->d.pair_data.car);
834
835 if (real->d.pair_data.cdr != NULL)
836 gconf_value_free(real->d.pair_data.cdr);
837 break;
838 default:
839 break;
840 }
841
842 g_slice_free(GConfRealValue, real);
843 }
844
845 const char*
gconf_value_get_string(const GConfValue * value)846 gconf_value_get_string (const GConfValue *value)
847 {
848 g_return_val_if_fail (value != NULL, NULL);
849 g_return_val_if_fail (value->type == GCONF_VALUE_STRING, NULL);
850
851 return REAL_VALUE (value)->d.string_data;
852 }
853
854 char*
gconf_value_steal_string(GConfValue * value)855 gconf_value_steal_string (GConfValue *value)
856 {
857 char *string;
858 GConfRealValue *real;
859
860 g_return_val_if_fail (value != NULL, NULL);
861 g_return_val_if_fail (value->type == GCONF_VALUE_STRING, NULL);
862
863 real = REAL_VALUE (value);
864
865 string = real->d.string_data;
866 real->d.string_data = NULL;
867
868 return string;
869 }
870
871 int
gconf_value_get_int(const GConfValue * value)872 gconf_value_get_int (const GConfValue *value)
873 {
874 g_return_val_if_fail (value != NULL, 0);
875 g_return_val_if_fail (value->type == GCONF_VALUE_INT, 0);
876
877 return REAL_VALUE (value)->d.int_data;
878 }
879
880 double
gconf_value_get_float(const GConfValue * value)881 gconf_value_get_float (const GConfValue *value)
882 {
883 g_return_val_if_fail (value != NULL, 0.0);
884 g_return_val_if_fail (value->type == GCONF_VALUE_FLOAT, 0.0);
885
886 return REAL_VALUE (value)->d.float_data;
887 }
888
889 GConfValueType
gconf_value_get_list_type(const GConfValue * value)890 gconf_value_get_list_type (const GConfValue *value)
891 {
892 g_return_val_if_fail (value != NULL, GCONF_VALUE_INVALID);
893 g_return_val_if_fail (value->type == GCONF_VALUE_LIST, GCONF_VALUE_INVALID);
894
895 return REAL_VALUE (value)->d.list_data.type;
896 }
897
898 /**
899 * gconf_value_get_list:
900 * @value: a #GConfValue.
901 *
902 * Returns a #GSList containing #GConfValue objects. Each #GConfValue in
903 * the returned list will have the type returned by
904 * gconf_value_get_list_type(). Remember that the empty #GSList is equal to
905 * <symbol>NULL</symbol>. The list is not a copy; it is "owned" by the
906 * #GConfValue and will be destroyed when the #GConfValue is destroyed.
907 *
908 * Return value: (element-type GConfValue) (transfer none): a #GList.
909 */
910 GSList*
gconf_value_get_list(const GConfValue * value)911 gconf_value_get_list (const GConfValue *value)
912 {
913 g_return_val_if_fail (value != NULL, NULL);
914 g_return_val_if_fail (value->type == GCONF_VALUE_LIST, NULL);
915
916 return REAL_VALUE (value)->d.list_data.list;
917 }
918
919 GSList*
gconf_value_steal_list(GConfValue * value)920 gconf_value_steal_list (GConfValue *value)
921 {
922 GSList *list;
923 GConfRealValue *real;
924
925 g_return_val_if_fail (value != NULL, NULL);
926 g_return_val_if_fail (value->type == GCONF_VALUE_LIST, NULL);
927
928 real = REAL_VALUE (value);
929
930 list = real->d.list_data.list;
931 real->d.list_data.list = NULL;
932 return list;
933 }
934
935 GConfValue*
gconf_value_get_car(const GConfValue * value)936 gconf_value_get_car (const GConfValue *value)
937 {
938 g_return_val_if_fail (value != NULL, NULL);
939 g_return_val_if_fail (value->type == GCONF_VALUE_PAIR, NULL);
940
941 return REAL_VALUE (value)->d.pair_data.car;
942 }
943
944 GConfValue*
gconf_value_get_cdr(const GConfValue * value)945 gconf_value_get_cdr (const GConfValue *value)
946 {
947 g_return_val_if_fail (value != NULL, NULL);
948 g_return_val_if_fail (value->type == GCONF_VALUE_PAIR, NULL);
949
950 return REAL_VALUE (value)->d.pair_data.cdr;
951 }
952
953
954 gboolean
gconf_value_get_bool(const GConfValue * value)955 gconf_value_get_bool (const GConfValue *value)
956 {
957 g_return_val_if_fail (value != NULL, FALSE);
958 g_return_val_if_fail (value->type == GCONF_VALUE_BOOL, FALSE);
959
960 return REAL_VALUE (value)->d.bool_data;
961 }
962
963 GConfSchema*
gconf_value_get_schema(const GConfValue * value)964 gconf_value_get_schema (const GConfValue *value)
965 {
966 g_return_val_if_fail (value != NULL, NULL);
967 g_return_val_if_fail (value->type == GCONF_VALUE_SCHEMA, NULL);
968
969 return REAL_VALUE (value)->d.schema_data;
970 }
971
972 GConfSchema*
gconf_value_steal_schema(GConfValue * value)973 gconf_value_steal_schema (GConfValue *value)
974 {
975 GConfSchema *schema;
976 GConfRealValue *real;
977
978 g_return_val_if_fail (value != NULL, NULL);
979 g_return_val_if_fail (value->type == GCONF_VALUE_SCHEMA, NULL);
980
981 real = REAL_VALUE (value);
982
983 schema = real->d.schema_data;
984 real->d.schema_data = NULL;
985
986 return schema;
987 }
988
989 void
gconf_value_set_int(GConfValue * value,gint the_int)990 gconf_value_set_int(GConfValue* value, gint the_int)
991 {
992 g_return_if_fail(value != NULL);
993 g_return_if_fail(value->type == GCONF_VALUE_INT);
994
995 REAL_VALUE (value)->d.int_data = the_int;
996 }
997
998 void
gconf_value_set_string(GConfValue * value,const gchar * the_str)999 gconf_value_set_string(GConfValue* value, const gchar* the_str)
1000 {
1001 gconf_value_set_string_nocopy (value,
1002 g_strdup (the_str));
1003 }
1004
1005 void
gconf_value_set_string_nocopy(GConfValue * value,char * str)1006 gconf_value_set_string_nocopy (GConfValue *value,
1007 char *str)
1008 {
1009 GConfRealValue *real;
1010
1011 g_return_if_fail(value != NULL);
1012 g_return_if_fail(value->type == GCONF_VALUE_STRING);
1013
1014 real = REAL_VALUE (value);
1015
1016 g_free (real->d.string_data);
1017 real->d.string_data = str;
1018 }
1019
1020 void
gconf_value_set_float(GConfValue * value,gdouble the_float)1021 gconf_value_set_float(GConfValue* value, gdouble the_float)
1022 {
1023 g_return_if_fail(value != NULL);
1024 g_return_if_fail(value->type == GCONF_VALUE_FLOAT);
1025
1026 REAL_VALUE (value)->d.float_data = the_float;
1027 }
1028
1029 void
gconf_value_set_bool(GConfValue * value,gboolean the_bool)1030 gconf_value_set_bool(GConfValue* value, gboolean the_bool)
1031 {
1032 g_return_if_fail(value != NULL);
1033 g_return_if_fail(value->type == GCONF_VALUE_BOOL);
1034
1035 REAL_VALUE (value)->d.bool_data = the_bool;
1036 }
1037
1038 void
gconf_value_set_schema(GConfValue * value,const GConfSchema * sc)1039 gconf_value_set_schema(GConfValue* value, const GConfSchema* sc)
1040 {
1041 GConfRealValue *real;
1042
1043 g_return_if_fail(value != NULL);
1044 g_return_if_fail(value->type == GCONF_VALUE_SCHEMA);
1045
1046 real = REAL_VALUE (value);
1047
1048 if (real->d.schema_data != NULL)
1049 gconf_schema_free (real->d.schema_data);
1050
1051 real->d.schema_data = gconf_schema_copy (sc);
1052 }
1053
1054 void
gconf_value_set_schema_nocopy(GConfValue * value,GConfSchema * sc)1055 gconf_value_set_schema_nocopy(GConfValue* value, GConfSchema* sc)
1056 {
1057 GConfRealValue *real;
1058
1059 g_return_if_fail(value != NULL);
1060 g_return_if_fail(value->type == GCONF_VALUE_SCHEMA);
1061 g_return_if_fail(sc != NULL);
1062
1063 real = REAL_VALUE (value);
1064
1065 if (real->d.schema_data != NULL)
1066 gconf_schema_free (real->d.schema_data);
1067
1068 real->d.schema_data = sc;
1069 }
1070
1071 void
gconf_value_set_car(GConfValue * value,const GConfValue * car)1072 gconf_value_set_car(GConfValue* value, const GConfValue* car)
1073 {
1074 gconf_value_set_car_nocopy(value, gconf_value_copy(car));
1075 }
1076
1077 void
gconf_value_set_car_nocopy(GConfValue * value,GConfValue * car)1078 gconf_value_set_car_nocopy(GConfValue* value, GConfValue* car)
1079 {
1080 GConfRealValue *real;
1081
1082 g_return_if_fail(value != NULL);
1083 g_return_if_fail(value->type == GCONF_VALUE_PAIR);
1084
1085 real = REAL_VALUE (value);
1086
1087 if (real->d.pair_data.car != NULL)
1088 gconf_value_free (real->d.pair_data.car);
1089
1090 real->d.pair_data.car = car;
1091 }
1092
1093 void
gconf_value_set_cdr(GConfValue * value,const GConfValue * cdr)1094 gconf_value_set_cdr(GConfValue* value, const GConfValue* cdr)
1095 {
1096 gconf_value_set_cdr_nocopy(value, gconf_value_copy(cdr));
1097 }
1098
1099 void
gconf_value_set_cdr_nocopy(GConfValue * value,GConfValue * cdr)1100 gconf_value_set_cdr_nocopy(GConfValue* value, GConfValue* cdr)
1101 {
1102 GConfRealValue *real;
1103
1104 g_return_if_fail(value != NULL);
1105 g_return_if_fail(value->type == GCONF_VALUE_PAIR);
1106
1107 real = REAL_VALUE (value);
1108
1109 if (real->d.pair_data.cdr != NULL)
1110 gconf_value_free (real->d.pair_data.cdr);
1111
1112 real->d.pair_data.cdr = cdr;
1113 }
1114
1115 void
gconf_value_set_list_type(GConfValue * value,GConfValueType type)1116 gconf_value_set_list_type (GConfValue *value,
1117 GConfValueType type)
1118 {
1119 GConfRealValue *real;
1120
1121 g_return_if_fail(value != NULL);
1122 g_return_if_fail(value->type == GCONF_VALUE_LIST);
1123 g_return_if_fail(type != GCONF_VALUE_LIST);
1124 g_return_if_fail(type != GCONF_VALUE_PAIR);
1125
1126 real = REAL_VALUE (value);
1127
1128 /* If the list is non-NULL either we already have the right
1129 * type, or we shouldn't be changing it without deleting
1130 * the list first.
1131 */
1132 g_return_if_fail (real->d.list_data.list == NULL);
1133
1134 real->d.list_data.type = type;
1135 }
1136
1137 void
gconf_value_set_list_nocopy(GConfValue * value,GSList * list)1138 gconf_value_set_list_nocopy (GConfValue* value,
1139 GSList* list)
1140 {
1141 GConfRealValue *real;
1142
1143 g_return_if_fail (value != NULL);
1144 g_return_if_fail (value->type == GCONF_VALUE_LIST);
1145
1146 real = REAL_VALUE (value);
1147
1148 g_return_if_fail (real->d.list_data.type != GCONF_VALUE_INVALID);
1149
1150 if (real->d.list_data.list)
1151 gconf_value_free_list (value);
1152
1153 real->d.list_data.list = list;
1154 }
1155
1156 void
gconf_value_set_list(GConfValue * value,GSList * list)1157 gconf_value_set_list (GConfValue* value,
1158 GSList* list)
1159 {
1160 GConfRealValue *real;
1161
1162 g_return_if_fail (value != NULL);
1163 g_return_if_fail (value->type == GCONF_VALUE_LIST);
1164
1165 real = REAL_VALUE (value);
1166
1167 g_return_if_fail (real->d.list_data.type != GCONF_VALUE_INVALID);
1168 g_return_if_fail ((list == NULL) ||
1169 ((list->data != NULL) &&
1170 (((GConfValue*)list->data)->type == real->d.list_data.type)));
1171
1172 if (real->d.list_data.list)
1173 gconf_value_free_list (value);
1174
1175 real->d.list_data.list = copy_value_list (list);
1176 }
1177
1178
1179 static int
null_safe_strcmp(const char * lhs,const char * rhs)1180 null_safe_strcmp (const char *lhs,
1181 const char *rhs)
1182 {
1183 if (lhs == NULL && rhs == NULL)
1184 return 0;
1185 else if (lhs == NULL)
1186 return -1;
1187 else if (rhs == NULL)
1188 return 1;
1189 else
1190 return strcmp (lhs, rhs);
1191 }
1192
1193 int
gconf_value_compare(const GConfValue * value_a,const GConfValue * value_b)1194 gconf_value_compare (const GConfValue *value_a,
1195 const GConfValue *value_b)
1196 {
1197 g_return_val_if_fail (value_a != NULL, 0);
1198 g_return_val_if_fail (value_b != NULL, 0);
1199
1200 /* Impose arbitrary type ordering, just to keep the
1201 * sort invariants stable.
1202 */
1203 if (value_a->type < value_b->type)
1204 return -1;
1205 else if (value_a->type > value_b->type)
1206 return 1;
1207
1208 switch (value_a->type)
1209 {
1210 case GCONF_VALUE_INT:
1211 if (gconf_value_get_int (value_a) < gconf_value_get_int (value_b))
1212 return -1;
1213 else if (gconf_value_get_int (value_a) > gconf_value_get_int (value_b))
1214 return 1;
1215 else
1216 return 0;
1217 case GCONF_VALUE_FLOAT:
1218 if (gconf_value_get_float (value_a) < gconf_value_get_float (value_b))
1219 return -1;
1220 else if (gconf_value_get_float (value_a) > gconf_value_get_float (value_b))
1221 return 1;
1222 else
1223 return 0;
1224 case GCONF_VALUE_STRING:
1225 return strcmp (gconf_value_get_string (value_a),
1226 gconf_value_get_string (value_b));
1227 case GCONF_VALUE_BOOL:
1228 if (gconf_value_get_bool (value_a) == gconf_value_get_bool (value_b))
1229 return 0;
1230 /* make TRUE > FALSE to maintain sort invariants */
1231 else if (gconf_value_get_bool (value_a))
1232 return 1;
1233 else
1234 return -1;
1235 case GCONF_VALUE_LIST:
1236 {
1237 GSList *list_a;
1238 GSList *list_b;
1239
1240 list_a = gconf_value_get_list (value_a);
1241 list_b = gconf_value_get_list (value_b);
1242
1243 while (list_a != NULL && list_b != NULL)
1244 {
1245 int result;
1246
1247 result = gconf_value_compare (list_a->data, list_b->data);
1248
1249 if (result != 0)
1250 return result;
1251
1252 list_a = g_slist_next (list_a);
1253 list_b = g_slist_next (list_b);
1254 }
1255
1256 if (list_a)
1257 return 1; /* list_a is longer so "greater" */
1258 else if (list_b)
1259 return -1;
1260 else
1261 return 0;
1262 }
1263 case GCONF_VALUE_PAIR:
1264 {
1265 GConfValue *a_car, *b_car, *a_cdr, *b_cdr;
1266 int result;
1267
1268 a_car = gconf_value_get_car (value_a);
1269 b_car = gconf_value_get_car (value_b);
1270 a_cdr = gconf_value_get_cdr (value_a);
1271 b_cdr = gconf_value_get_cdr (value_b);
1272
1273 if (a_car == NULL && b_car != NULL)
1274 return -1;
1275 else if (a_car != NULL && b_car == NULL)
1276 return 1;
1277 else if (a_car != NULL && b_car != NULL)
1278 {
1279 result = gconf_value_compare (a_car, b_car);
1280
1281 if (result != 0)
1282 return result;
1283 }
1284
1285 if (a_cdr == NULL && b_cdr != NULL)
1286 return -1;
1287 else if (a_cdr != NULL && b_cdr == NULL)
1288 return 1;
1289 else if (a_cdr != NULL && b_cdr != NULL)
1290 {
1291 result = gconf_value_compare (a_cdr, b_cdr);
1292
1293 if (result != 0)
1294 return result;
1295 }
1296
1297 return 0;
1298 }
1299 case GCONF_VALUE_INVALID:
1300 return 0;
1301 case GCONF_VALUE_SCHEMA:
1302 {
1303 const char *locale_a, *locale_b;
1304 GConfValueType type_a, type_b;
1305 GConfValueType list_type_a, list_type_b;
1306 GConfValueType car_type_a, car_type_b;
1307 GConfValueType cdr_type_a, cdr_type_b;
1308 const char *short_desc_a, *short_desc_b;
1309 const char *long_desc_a, *long_desc_b;
1310 int result;
1311
1312 type_a = gconf_schema_get_type (gconf_value_get_schema (value_a));
1313 type_b = gconf_schema_get_type (gconf_value_get_schema (value_b));
1314
1315 if (type_a < type_b)
1316 return -1;
1317 else if (type_a > type_b)
1318 return 1;
1319
1320 short_desc_a = gconf_schema_get_short_desc (gconf_value_get_schema (value_a));
1321 short_desc_b = gconf_schema_get_short_desc (gconf_value_get_schema (value_b));
1322
1323 result = null_safe_strcmp (short_desc_a, short_desc_b);
1324 if (result != 0)
1325 return result;
1326
1327 long_desc_a = gconf_schema_get_long_desc (gconf_value_get_schema (value_a));
1328
1329
1330 long_desc_b = gconf_schema_get_long_desc (gconf_value_get_schema (value_b));
1331
1332 result = null_safe_strcmp (long_desc_a, long_desc_b);
1333 if (result != 0)
1334 return result;
1335
1336 locale_a = gconf_schema_get_locale (gconf_value_get_schema (value_a));
1337 locale_b = gconf_schema_get_locale (gconf_value_get_schema (value_b));
1338
1339 result = null_safe_strcmp (locale_a, locale_b);
1340 if (result != 0)
1341 return result;
1342
1343 if (type_a == GCONF_VALUE_LIST)
1344 {
1345 list_type_a = gconf_schema_get_list_type (gconf_value_get_schema (value_a));
1346 list_type_b = gconf_schema_get_list_type (gconf_value_get_schema (value_b));
1347
1348 if (list_type_a < list_type_b)
1349 return -1;
1350 else if (list_type_a > list_type_b)
1351 return 1;
1352 }
1353
1354 if (type_a == GCONF_VALUE_PAIR)
1355 {
1356 car_type_a = gconf_schema_get_car_type (gconf_value_get_schema (value_a));
1357 car_type_b = gconf_schema_get_car_type (gconf_value_get_schema (value_b));
1358
1359 if (car_type_a < car_type_b)
1360 return -1;
1361 else if (car_type_a > car_type_b)
1362 return 1;
1363
1364 cdr_type_a = gconf_schema_get_cdr_type (gconf_value_get_schema (value_a));
1365 cdr_type_b = gconf_schema_get_cdr_type (gconf_value_get_schema (value_b));
1366
1367 if (cdr_type_a < cdr_type_b)
1368 return -1;
1369 else if (cdr_type_a > cdr_type_b)
1370 return 1;
1371 }
1372
1373 return 0;
1374 }
1375 }
1376
1377 g_assert_not_reached ();
1378
1379 return 0;
1380 }
1381
1382 /*
1383 * GConfMetaInfo
1384 */
1385
1386 GConfMetaInfo*
gconf_meta_info_new(void)1387 gconf_meta_info_new(void)
1388 {
1389 GConfMetaInfo* gcmi;
1390
1391 gcmi = g_new0(GConfMetaInfo, 1);
1392
1393 /* pointers and time are NULL/0 */
1394
1395 return gcmi;
1396 }
1397
1398 void
gconf_meta_info_free(GConfMetaInfo * gcmi)1399 gconf_meta_info_free(GConfMetaInfo* gcmi)
1400 {
1401 set_string(&gcmi->schema, NULL);
1402 set_string(&gcmi->mod_user, NULL);
1403 g_free(gcmi);
1404 }
1405
1406 const char*
gconf_meta_info_get_schema(GConfMetaInfo * gcmi)1407 gconf_meta_info_get_schema (GConfMetaInfo *gcmi)
1408 {
1409 g_return_val_if_fail (gcmi != NULL, NULL);
1410
1411 return gcmi->schema;
1412 }
1413
1414 const char*
gconf_meta_info_get_mod_user(GConfMetaInfo * gcmi)1415 gconf_meta_info_get_mod_user (GConfMetaInfo *gcmi)
1416 {
1417 g_return_val_if_fail (gcmi != NULL, NULL);
1418
1419 return gcmi->mod_user;
1420 }
1421
1422 GTime
gconf_meta_info_mod_time(GConfMetaInfo * gcmi)1423 gconf_meta_info_mod_time (GConfMetaInfo *gcmi)
1424 {
1425 g_return_val_if_fail (gcmi != NULL, 0);
1426
1427 return gcmi->mod_time;
1428 }
1429
1430 void
gconf_meta_info_set_schema(GConfMetaInfo * gcmi,const gchar * schema_name)1431 gconf_meta_info_set_schema (GConfMetaInfo* gcmi,
1432 const gchar* schema_name)
1433 {
1434 set_string(&gcmi->schema, schema_name);
1435 }
1436
1437 void
gconf_meta_info_set_mod_user(GConfMetaInfo * gcmi,const gchar * mod_user)1438 gconf_meta_info_set_mod_user(GConfMetaInfo* gcmi,
1439 const gchar* mod_user)
1440 {
1441 set_string(&gcmi->mod_user, mod_user);
1442 }
1443
1444 void
gconf_meta_info_set_mod_time(GConfMetaInfo * gcmi,GTime mod_time)1445 gconf_meta_info_set_mod_time(GConfMetaInfo* gcmi,
1446 GTime mod_time)
1447 {
1448 gcmi->mod_time = mod_time;
1449 }
1450
1451 /*
1452 * GConfEntry
1453 */
1454
1455 typedef struct {
1456 char *key;
1457 GConfValue *value;
1458 char *schema_name;
1459 int refcount;
1460 guint is_default : 1;
1461 guint is_writable : 1;
1462 } GConfRealEntry;
1463
1464 #define REAL_ENTRY(x) ((GConfRealEntry*)(x))
1465
1466 GType
gconf_entry_get_type()1467 gconf_entry_get_type ()
1468 {
1469 static GType type = 0;
1470
1471 if (type == 0)
1472 type = g_boxed_type_register_static (g_intern_static_string ("GConfEntry"),
1473 (GBoxedCopyFunc) gconf_entry_ref,
1474 (GBoxedFreeFunc) gconf_entry_unref);
1475 return type;
1476 }
1477
1478 GConfEntry*
gconf_entry_new(const char * key,const GConfValue * val)1479 gconf_entry_new (const char *key,
1480 const GConfValue *val)
1481 {
1482 return gconf_entry_new_nocopy (g_strdup (key),
1483 val ? gconf_value_copy (val) : NULL);
1484
1485 }
1486
1487 GConfEntry*
gconf_entry_new_nocopy(char * key,GConfValue * val)1488 gconf_entry_new_nocopy (char* key, GConfValue* val)
1489 {
1490 GConfRealEntry* real;
1491
1492 real = g_slice_new (GConfRealEntry);
1493
1494 real->key = key;
1495 real->value = val;
1496 real->schema_name = NULL;
1497 real->is_default = FALSE;
1498 real->is_writable = TRUE;
1499 real->refcount = 1;
1500
1501 return (GConfEntry*) real;
1502 }
1503
1504 GConfEntry *
gconf_entry_ref(GConfEntry * entry)1505 gconf_entry_ref (GConfEntry *entry)
1506 {
1507 g_return_val_if_fail (entry != NULL, NULL);
1508
1509 REAL_ENTRY (entry)->refcount += 1;
1510
1511 return entry;
1512 }
1513
1514 void
gconf_entry_unref(GConfEntry * entry)1515 gconf_entry_unref (GConfEntry *entry)
1516 {
1517 GConfRealEntry *real;
1518
1519 g_return_if_fail (entry != NULL);
1520 g_return_if_fail (REAL_ENTRY (entry)->refcount > 0);
1521
1522 real = REAL_ENTRY (entry);
1523
1524 real->refcount -= 1;
1525
1526 if (real->refcount == 0)
1527 {
1528 g_free (real->key);
1529 if (real->value)
1530 gconf_value_free (real->value);
1531 g_free (real->schema_name);
1532 g_slice_free (GConfRealEntry, real);
1533 }
1534 }
1535
1536 void
gconf_entry_free(GConfEntry * entry)1537 gconf_entry_free (GConfEntry *entry)
1538 {
1539 gconf_entry_unref (entry);
1540 }
1541
1542 GConfEntry*
gconf_entry_copy(const GConfEntry * src)1543 gconf_entry_copy (const GConfEntry *src)
1544 {
1545 GConfEntry *entry;
1546 GConfRealEntry *real;
1547
1548 entry = gconf_entry_new (REAL_ENTRY (src)->key,
1549 REAL_ENTRY (src)->value);
1550 real = REAL_ENTRY (entry);
1551
1552 real->schema_name = g_strdup (REAL_ENTRY (src)->schema_name);
1553 real->is_default = REAL_ENTRY (src)->is_default;
1554 real->is_writable = REAL_ENTRY (src)->is_writable;
1555
1556 return entry;
1557 }
1558
1559 gboolean
gconf_entry_equal(const GConfEntry * a,const GConfEntry * b)1560 gconf_entry_equal (const GConfEntry *a,
1561 const GConfEntry *b)
1562 {
1563 GConfRealEntry *real_a;
1564 GConfRealEntry *real_b;
1565
1566 g_return_val_if_fail (a != NULL, FALSE);
1567 g_return_val_if_fail (b != NULL, FALSE);
1568
1569 real_a = REAL_ENTRY (a);
1570 real_b = REAL_ENTRY (b);
1571
1572 /* do the cheap checks first, why not */
1573 if (real_a->value && !real_b->value)
1574 return FALSE;
1575 else if (!real_a->value && real_b->value)
1576 return FALSE;
1577 else if (real_a->is_default != real_b->is_default)
1578 return FALSE;
1579 else if (real_a->is_writable != real_b->is_writable)
1580 return FALSE;
1581 else if (strcmp (real_a->key, real_b->key) != 0)
1582 return FALSE;
1583 else if (real_a->schema_name && !real_b->schema_name)
1584 return FALSE;
1585 else if (!real_a->schema_name && real_b->schema_name)
1586 return FALSE;
1587 else if (real_a->schema_name && real_b->schema_name &&
1588 strcmp (real_a->schema_name, real_b->schema_name) != 0)
1589 return FALSE;
1590 else if (real_a->value && real_b->value &&
1591 gconf_value_compare (real_a->value, real_b->value) != 0)
1592 return FALSE;
1593 else
1594 return TRUE;
1595 }
1596
1597 GConfValue*
gconf_entry_steal_value(GConfEntry * entry)1598 gconf_entry_steal_value (GConfEntry* entry)
1599 {
1600 GConfValue* val = REAL_ENTRY (entry)->value;
1601 REAL_ENTRY (entry)->value = NULL;
1602 return val;
1603 }
1604
1605 const char*
gconf_entry_get_key(const GConfEntry * entry)1606 gconf_entry_get_key (const GConfEntry *entry)
1607 {
1608 g_return_val_if_fail (entry != NULL, NULL);
1609
1610 return REAL_ENTRY (entry)->key;
1611 }
1612
1613 GConfValue*
gconf_entry_get_value(const GConfEntry * entry)1614 gconf_entry_get_value (const GConfEntry *entry)
1615 {
1616 g_return_val_if_fail (entry != NULL, NULL);
1617
1618 return REAL_ENTRY (entry)->value;
1619 }
1620
1621 const char*
gconf_entry_get_schema_name(const GConfEntry * entry)1622 gconf_entry_get_schema_name (const GConfEntry *entry)
1623 {
1624 g_return_val_if_fail (entry != NULL, NULL);
1625
1626 return REAL_ENTRY (entry)->schema_name;
1627 }
1628
1629 gboolean
gconf_entry_get_is_default(const GConfEntry * entry)1630 gconf_entry_get_is_default (const GConfEntry *entry)
1631 {
1632 g_return_val_if_fail (entry != NULL, FALSE);
1633
1634 return REAL_ENTRY (entry)->is_default;
1635 }
1636
1637 gboolean
gconf_entry_get_is_writable(const GConfEntry * entry)1638 gconf_entry_get_is_writable (const GConfEntry *entry)
1639 {
1640 g_return_val_if_fail (entry != NULL, FALSE);
1641
1642 return REAL_ENTRY (entry)->is_writable;
1643 }
1644
1645
1646 void
gconf_entry_set_value(GConfEntry * entry,const GConfValue * val)1647 gconf_entry_set_value (GConfEntry *entry,
1648 const GConfValue *val)
1649 {
1650 gconf_entry_set_value_nocopy (entry,
1651 val ? gconf_value_copy (val) : NULL);
1652 }
1653
1654 void
gconf_entry_set_value_nocopy(GConfEntry * entry,GConfValue * val)1655 gconf_entry_set_value_nocopy(GConfEntry* entry,
1656 GConfValue* val)
1657 {
1658 if (REAL_ENTRY (entry)->value)
1659 gconf_value_free (REAL_ENTRY (entry)->value);
1660
1661 REAL_ENTRY (entry)->value = val;
1662 }
1663
1664 void
gconf_entry_set_schema_name(GConfEntry * entry,const gchar * name)1665 gconf_entry_set_schema_name(GConfEntry* entry,
1666 const gchar* name)
1667 {
1668 g_free (REAL_ENTRY (entry)->schema_name);
1669
1670 REAL_ENTRY (entry)->schema_name = g_strdup(name);
1671 }
1672
1673 void
gconf_entry_set_is_default(GConfEntry * entry,gboolean is_default)1674 gconf_entry_set_is_default (GConfEntry* entry,
1675 gboolean is_default)
1676 {
1677 REAL_ENTRY (entry)->is_default = is_default;
1678 }
1679
1680 void
gconf_entry_set_is_writable(GConfEntry * entry,gboolean is_writable)1681 gconf_entry_set_is_writable (GConfEntry *entry,
1682 gboolean is_writable)
1683 {
1684 REAL_ENTRY (entry)->is_writable = is_writable;
1685 }
1686
1687
1688 gboolean
gconf_value_validate(const GConfValue * value,GError ** err)1689 gconf_value_validate (const GConfValue *value,
1690 GError **err)
1691 {
1692 GConfRealValue *real;
1693
1694 g_return_val_if_fail (value != NULL, FALSE);
1695
1696 real = REAL_VALUE (value);
1697
1698 switch (value->type)
1699 {
1700 case GCONF_VALUE_STRING:
1701 if (real->d.string_data &&
1702 !g_utf8_validate (real->d.string_data, -1, NULL))
1703 {
1704 g_set_error (err, GCONF_ERROR,
1705 GCONF_ERROR_FAILED,
1706 _("Text contains invalid UTF-8"));
1707 return FALSE;
1708 }
1709 break;
1710
1711 case GCONF_VALUE_SCHEMA:
1712 if (real->d.schema_data)
1713 return gconf_schema_validate (real->d.schema_data,
1714 err);
1715 break;
1716
1717 default:
1718 break;
1719 }
1720
1721 return TRUE;
1722 }
1723