use g_type_is_a() to check for object_type being a G_TYPE_OBJECT, not
[platform/upstream/glib.git] / gobject / gparamspecs.c
1 /* GObject - GLib Type, Object, Parameter and Signal Library
2  * Copyright (C) 1997-1999, 2000-2001 Tim Janik and 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 Lesser 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  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General
15  * Public License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * MT safe
22  */
23
24 #include        "gparamspecs.h"
25
26 #include        "gvaluecollector.h"
27 #include        "gvaluearray.h"
28 #include        <string.h>
29 #include        "../config.h"   /* for SIZEOF_LONG */
30
31 #define G_FLOAT_EPSILON         (1e-30)
32 #define G_DOUBLE_EPSILON        (1e-90)
33
34
35 /* --- param spec functions --- */
36 static void
37 param_char_init (GParamSpec *pspec)
38 {
39   GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
40   
41   cspec->minimum = 0x7f;
42   cspec->maximum = 0x80;
43   cspec->default_value = 0;
44 }
45
46 static void
47 param_char_set_default (GParamSpec *pspec,
48                         GValue     *value)
49 {
50   value->data[0].v_int = G_PARAM_SPEC_CHAR (pspec)->default_value;
51 }
52
53 static gboolean
54 param_char_validate (GParamSpec *pspec,
55                      GValue     *value)
56 {
57   GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
58   gint oval = value->data[0].v_int;
59   
60   value->data[0].v_int = CLAMP (value->data[0].v_int, cspec->minimum, cspec->maximum);
61   
62   return value->data[0].v_int != oval;
63 }
64
65 static void
66 param_uchar_init (GParamSpec *pspec)
67 {
68   GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
69   
70   uspec->minimum = 0;
71   uspec->maximum = 0xff;
72   uspec->default_value = 0;
73 }
74
75 static void
76 param_uchar_set_default (GParamSpec *pspec,
77                          GValue     *value)
78 {
79   value->data[0].v_uint = G_PARAM_SPEC_UCHAR (pspec)->default_value;
80 }
81
82 static gboolean
83 param_uchar_validate (GParamSpec *pspec,
84                       GValue     *value)
85 {
86   GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
87   guint oval = value->data[0].v_uint;
88   
89   value->data[0].v_uint = CLAMP (value->data[0].v_uint, uspec->minimum, uspec->maximum);
90   
91   return value->data[0].v_uint != oval;
92 }
93
94 static void
95 param_boolean_set_default (GParamSpec *pspec,
96                            GValue     *value)
97 {
98   value->data[0].v_int = G_PARAM_SPEC_BOOLEAN (pspec)->default_value;
99 }
100
101 static gboolean
102 param_boolean_validate (GParamSpec *pspec,
103                         GValue     *value)
104 {
105   gint oval = value->data[0].v_int;
106   
107   value->data[0].v_int = value->data[0].v_int != FALSE;
108   
109   return value->data[0].v_int != oval;
110 }
111
112 static void
113 param_int_init (GParamSpec *pspec)
114 {
115   GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
116   
117   ispec->minimum = 0x7fffffff;
118   ispec->maximum = 0x80000000;
119   ispec->default_value = 0;
120 }
121
122 static void
123 param_int_set_default (GParamSpec *pspec,
124                        GValue     *value)
125 {
126   value->data[0].v_int = G_PARAM_SPEC_INT (pspec)->default_value;
127 }
128
129 static gboolean
130 param_int_validate (GParamSpec *pspec,
131                     GValue     *value)
132 {
133   GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
134   gint oval = value->data[0].v_int;
135   
136   value->data[0].v_int = CLAMP (value->data[0].v_int, ispec->minimum, ispec->maximum);
137   
138   return value->data[0].v_int != oval;
139 }
140
141 static gint
142 param_int_values_cmp (GParamSpec   *pspec,
143                       const GValue *value1,
144                       const GValue *value2)
145 {
146   if (value1->data[0].v_int < value2->data[0].v_int)
147     return -1;
148   else
149     return value1->data[0].v_int > value2->data[0].v_int;
150 }
151
152 static void
153 param_uint_init (GParamSpec *pspec)
154 {
155   GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
156   
157   uspec->minimum = 0;
158   uspec->maximum = 0xffffffff;
159   uspec->default_value = 0;
160 }
161
162 static void
163 param_uint_set_default (GParamSpec *pspec,
164                         GValue     *value)
165 {
166   value->data[0].v_uint = G_PARAM_SPEC_UINT (pspec)->default_value;
167 }
168
169 static gboolean
170 param_uint_validate (GParamSpec *pspec,
171                      GValue     *value)
172 {
173   GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
174   guint oval = value->data[0].v_uint;
175   
176   value->data[0].v_uint = CLAMP (value->data[0].v_uint, uspec->minimum, uspec->maximum);
177   
178   return value->data[0].v_uint != oval;
179 }
180
181 static gint
182 param_uint_values_cmp (GParamSpec   *pspec,
183                        const GValue *value1,
184                        const GValue *value2)
185 {
186   if (value1->data[0].v_uint < value2->data[0].v_uint)
187     return -1;
188   else
189     return value1->data[0].v_uint > value2->data[0].v_uint;
190 }
191
192 static void
193 param_long_init (GParamSpec *pspec)
194 {
195   GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
196   
197 #if SIZEOF_LONG == 4
198   lspec->minimum = 0x7fffffff;
199   lspec->maximum = 0x80000000;
200 #else /* SIZEOF_LONG != 4 (8) */
201   lspec->minimum = 0x7fffffffffffffff;
202   lspec->maximum = 0x8000000000000000;
203 #endif
204   lspec->default_value = 0;
205 }
206
207 static void
208 param_long_set_default (GParamSpec *pspec,
209                         GValue     *value)
210 {
211   value->data[0].v_long = G_PARAM_SPEC_LONG (pspec)->default_value;
212 }
213
214 static gboolean
215 param_long_validate (GParamSpec *pspec,
216                      GValue     *value)
217 {
218   GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
219   glong oval = value->data[0].v_long;
220   
221   value->data[0].v_long = CLAMP (value->data[0].v_long, lspec->minimum, lspec->maximum);
222   
223   return value->data[0].v_long != oval;
224 }
225
226 static gint
227 param_long_values_cmp (GParamSpec   *pspec,
228                        const GValue *value1,
229                        const GValue *value2)
230 {
231   if (value1->data[0].v_long < value2->data[0].v_long)
232     return -1;
233   else
234     return value1->data[0].v_long > value2->data[0].v_long;
235 }
236
237 static void
238 param_ulong_init (GParamSpec *pspec)
239 {
240   GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
241   
242   uspec->minimum = 0;
243 #if SIZEOF_LONG == 4
244   uspec->maximum = 0xffffffff;
245 #else /* SIZEOF_LONG != 4 (8) */
246   uspec->maximum = 0xffffffffffffffff;
247 #endif
248   uspec->default_value = 0;
249 }
250
251 static void
252 param_ulong_set_default (GParamSpec *pspec,
253                          GValue     *value)
254 {
255   value->data[0].v_ulong = G_PARAM_SPEC_ULONG (pspec)->default_value;
256 }
257
258 static gboolean
259 param_ulong_validate (GParamSpec *pspec,
260                       GValue     *value)
261 {
262   GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
263   gulong oval = value->data[0].v_ulong;
264   
265   value->data[0].v_ulong = CLAMP (value->data[0].v_ulong, uspec->minimum, uspec->maximum);
266   
267   return value->data[0].v_ulong != oval;
268 }
269
270 static gint
271 param_ulong_values_cmp (GParamSpec   *pspec,
272                         const GValue *value1,
273                         const GValue *value2)
274 {
275   if (value1->data[0].v_ulong < value2->data[0].v_ulong)
276     return -1;
277   else
278     return value1->data[0].v_ulong > value2->data[0].v_ulong;
279 }
280
281 static void
282 param_enum_init (GParamSpec *pspec)
283 {
284   GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
285   
286   espec->enum_class = NULL;
287   espec->default_value = 0;
288 }
289
290 static void
291 param_enum_finalize (GParamSpec *pspec)
292 {
293   GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
294   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_ENUM));
295   
296   if (espec->enum_class)
297     {
298       g_type_class_unref (espec->enum_class);
299       espec->enum_class = NULL;
300     }
301   
302   parent_class->finalize (pspec);
303 }
304
305 static void
306 param_enum_set_default (GParamSpec *pspec,
307                         GValue     *value)
308 {
309   value->data[0].v_long = G_PARAM_SPEC_ENUM (pspec)->default_value;
310 }
311
312 static gboolean
313 param_enum_validate (GParamSpec *pspec,
314                      GValue     *value)
315 {
316   GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
317   glong oval = value->data[0].v_long;
318   
319   if (!espec->enum_class ||
320       !g_enum_get_value (espec->enum_class, value->data[0].v_long))
321     value->data[0].v_long = espec->default_value;
322   
323   return value->data[0].v_long != oval;
324 }
325
326 static void
327 param_flags_init (GParamSpec *pspec)
328 {
329   GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
330   
331   fspec->flags_class = NULL;
332   fspec->default_value = 0;
333 }
334
335 static void
336 param_flags_finalize (GParamSpec *pspec)
337 {
338   GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
339   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_FLAGS));
340   
341   if (fspec->flags_class)
342     {
343       g_type_class_unref (fspec->flags_class);
344       fspec->flags_class = NULL;
345     }
346   
347   parent_class->finalize (pspec);
348 }
349
350 static void
351 param_flags_set_default (GParamSpec *pspec,
352                          GValue     *value)
353 {
354   value->data[0].v_ulong = G_PARAM_SPEC_FLAGS (pspec)->default_value;
355 }
356
357 static gboolean
358 param_flags_validate (GParamSpec *pspec,
359                       GValue     *value)
360 {
361   GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
362   gulong oval = value->data[0].v_ulong;
363   
364   if (fspec->flags_class)
365     value->data[0].v_ulong &= fspec->flags_class->mask;
366   else
367     value->data[0].v_ulong = fspec->default_value;
368   
369   return value->data[0].v_ulong != oval;
370 }
371
372 static void
373 param_float_init (GParamSpec *pspec)
374 {
375   GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
376   
377   fspec->minimum = G_MINFLOAT;
378   fspec->maximum = G_MAXFLOAT;
379   fspec->default_value = 0;
380   fspec->epsilon = G_FLOAT_EPSILON;
381 }
382
383 static void
384 param_float_set_default (GParamSpec *pspec,
385                          GValue     *value)
386 {
387   value->data[0].v_float = G_PARAM_SPEC_FLOAT (pspec)->default_value;
388 }
389
390 static gboolean
391 param_float_validate (GParamSpec *pspec,
392                       GValue     *value)
393 {
394   GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
395   gfloat oval = value->data[0].v_float;
396   
397   value->data[0].v_float = CLAMP (value->data[0].v_float, fspec->minimum, fspec->maximum);
398   
399   return value->data[0].v_float != oval;
400 }
401
402 static gint
403 param_float_values_cmp (GParamSpec   *pspec,
404                         const GValue *value1,
405                         const GValue *value2)
406 {
407   gfloat epsilon = G_PARAM_SPEC_FLOAT (pspec)->epsilon;
408   
409   if (value1->data[0].v_float < value2->data[0].v_float)
410     return - (value2->data[0].v_float - value1->data[0].v_float > epsilon);
411   else
412     return value1->data[0].v_float - value2->data[0].v_float > epsilon;
413 }
414
415 static void
416 param_double_init (GParamSpec *pspec)
417 {
418   GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
419   
420   dspec->minimum = G_MINDOUBLE;
421   dspec->maximum = G_MAXDOUBLE;
422   dspec->default_value = 0;
423   dspec->epsilon = G_DOUBLE_EPSILON;
424 }
425
426 static void
427 param_double_set_default (GParamSpec *pspec,
428                           GValue     *value)
429 {
430   value->data[0].v_double = G_PARAM_SPEC_DOUBLE (pspec)->default_value;
431 }
432
433 static gboolean
434 param_double_validate (GParamSpec *pspec,
435                        GValue     *value)
436 {
437   GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
438   gdouble oval = value->data[0].v_double;
439   
440   value->data[0].v_double = CLAMP (value->data[0].v_double, dspec->minimum, dspec->maximum);
441   
442   return value->data[0].v_double != oval;
443 }
444
445 static gint
446 param_double_values_cmp (GParamSpec   *pspec,
447                          const GValue *value1,
448                          const GValue *value2)
449 {
450   gdouble epsilon = G_PARAM_SPEC_DOUBLE (pspec)->epsilon;
451   
452   if (value1->data[0].v_double < value2->data[0].v_double)
453     return - (value2->data[0].v_double - value1->data[0].v_double > epsilon);
454   else
455     return value1->data[0].v_double - value2->data[0].v_double > epsilon;
456 }
457
458 static void
459 param_string_init (GParamSpec *pspec)
460 {
461   GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
462   
463   sspec->default_value = NULL;
464   sspec->cset_first = NULL;
465   sspec->cset_nth = NULL;
466   sspec->substitutor = '_';
467   sspec->null_fold_if_empty = FALSE;
468   sspec->ensure_non_null = FALSE;
469 }
470
471 static void
472 param_string_finalize (GParamSpec *pspec)
473 {
474   GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
475   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_STRING));
476   
477   g_free (sspec->default_value);
478   g_free (sspec->cset_first);
479   g_free (sspec->cset_nth);
480   sspec->default_value = NULL;
481   sspec->cset_first = NULL;
482   sspec->cset_nth = NULL;
483   
484   parent_class->finalize (pspec);
485 }
486
487 static void
488 param_string_set_default (GParamSpec *pspec,
489                           GValue     *value)
490 {
491   value->data[0].v_pointer = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
492 }
493
494 static gboolean
495 param_string_validate (GParamSpec *pspec,
496                        GValue     *value)
497 {
498   GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
499   gchar *string = value->data[0].v_pointer;
500   guint changed = 0;
501   
502   if (string && string[0])
503     {
504       gchar *s;
505       
506       if (sspec->cset_first && !strchr (sspec->cset_first, string[0]))
507         {
508           string[0] = sspec->substitutor;
509           changed++;
510         }
511       if (sspec->cset_nth)
512         for (s = string + 1; *s; s++)
513           if (!strchr (sspec->cset_nth, *s))
514             {
515               *s = sspec->substitutor;
516               changed++;
517             }
518     }
519   if (sspec->null_fold_if_empty && string && string[0] == 0)
520     {
521       g_free (value->data[0].v_pointer);
522       value->data[0].v_pointer = NULL;
523       changed++;
524       string = value->data[0].v_pointer;
525     }
526   if (sspec->ensure_non_null && !string)
527     {
528       value->data[0].v_pointer = g_strdup ("");
529       changed++;
530       string = value->data[0].v_pointer;
531     }
532   
533   return changed;
534 }
535
536 static gint
537 param_string_values_cmp (GParamSpec   *pspec,
538                          const GValue *value1,
539                          const GValue *value2)
540 {
541   if (!value1->data[0].v_pointer)
542     return value2->data[0].v_pointer != NULL ? -1 : 0;
543   else if (!value2->data[0].v_pointer)
544     return value1->data[0].v_pointer != NULL;
545   else
546     return strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
547 }
548
549 static void
550 param_param_init (GParamSpec *pspec)
551 {
552   /* GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec); */
553 }
554
555 static void
556 param_param_set_default (GParamSpec *pspec,
557                          GValue     *value)
558 {
559   value->data[0].v_pointer = NULL;
560 }
561
562 static gboolean
563 param_param_validate (GParamSpec *pspec,
564                       GValue     *value)
565 {
566   /* GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec); */
567   GParamSpec *param = value->data[0].v_pointer;
568   guint changed = 0;
569   
570   if (param && !g_value_type_compatible (G_PARAM_SPEC_TYPE (param), G_PARAM_SPEC_VALUE_TYPE (pspec)))
571     {
572       g_param_spec_unref (param);
573       value->data[0].v_pointer = NULL;
574       changed++;
575     }
576   
577   return changed;
578 }
579
580 static void
581 param_boxed_init (GParamSpec *pspec)
582 {
583   /* GParamSpecBoxed *bspec = G_PARAM_SPEC_BOXED (pspec); */
584 }
585
586 static void
587 param_boxed_set_default (GParamSpec *pspec,
588                          GValue     *value)
589 {
590   value->data[0].v_pointer = NULL;
591 }
592
593 static gboolean
594 param_boxed_validate (GParamSpec *pspec,
595                       GValue     *value)
596 {
597   /* GParamSpecBoxed *bspec = G_PARAM_SPEC_BOXED (pspec); */
598   guint changed = 0;
599
600   /* can't do a whole lot here since we haven't even G_BOXED_TYPE() */
601   
602   return changed;
603 }
604
605 static gint
606 param_boxed_values_cmp (GParamSpec    *pspec,
607                          const GValue *value1,
608                          const GValue *value2)
609 {
610   guint8 *p1 = value1->data[0].v_pointer;
611   guint8 *p2 = value2->data[0].v_pointer;
612
613   /* not much to compare here, try to at least provide stable lesser/greater result */
614
615   return p1 < p2 ? -1 : p1 > p2;
616 }
617
618 static void
619 param_pointer_init (GParamSpec *pspec)
620 {
621   /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
622 }
623
624 static void
625 param_pointer_set_default (GParamSpec *pspec,
626                            GValue     *value)
627 {
628   value->data[0].v_pointer = NULL;
629 }
630
631 static gboolean
632 param_pointer_validate (GParamSpec *pspec,
633                         GValue     *value)
634 {
635   /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
636   guint changed = 0;
637   
638   return changed;
639 }
640
641 static gint
642 param_pointer_values_cmp (GParamSpec   *pspec,
643                           const GValue *value1,
644                           const GValue *value2)
645 {
646   guint8 *p1 = value1->data[0].v_pointer;
647   guint8 *p2 = value2->data[0].v_pointer;
648
649   /* not much to compare here, try to at least provide stable lesser/greater result */
650
651   return p1 < p2 ? -1 : p1 > p2;
652 }
653
654 static void
655 param_closure_init (GParamSpec *pspec)
656 {
657   /* GParamSpecClosure *cspec = G_PARAM_SPEC_CLOSURE (pspec); */
658 }
659
660 static void
661 param_closure_set_default (GParamSpec *pspec,
662                            GValue     *value)
663 {
664   value->data[0].v_pointer = NULL;
665 }
666
667 static gboolean
668 param_closure_validate (GParamSpec *pspec,
669                         GValue     *value)
670 {
671   /* GParamSpecClosure *cspec = G_PARAM_SPEC_CLOSURE (pspec); */
672   /* GClosure *closure = value->data[0].v_pointer; */
673   guint changed = 0;
674
675   /* we don't actually have necessary means to ensure closure validity */
676
677   return changed;
678 }
679
680 static gint
681 param_closure_values_cmp (GParamSpec   *pspec,
682                           const GValue *value1,
683                           const GValue *value2)
684 {
685   guint8 *p1 = value1->data[0].v_pointer;
686   guint8 *p2 = value2->data[0].v_pointer;
687
688   /* not much to compare here, try to at least provide stable lesser/greater result */
689
690   return p1 < p2 ? -1 : p1 > p2;
691 }
692
693 static void
694 param_value_array_init (GParamSpec *pspec)
695 {
696   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
697
698   aspec->element_spec = NULL;
699   aspec->fixed_n_elements = 0; /* disable */
700 }
701
702 static inline guint
703 value_array_ensure_size (GValueArray *value_array,
704                          guint        fixed_n_elements)
705 {
706   guint changed = 0;
707
708   if (fixed_n_elements)
709     {
710       while (value_array->n_values < fixed_n_elements)
711         {
712           g_value_array_append (value_array, NULL);
713           changed++;
714         }
715       while (value_array->n_values > fixed_n_elements)
716         {
717           g_value_array_remove (value_array, value_array->n_values - 1);
718           changed++;
719         }
720     }
721   return changed;
722 }
723
724 static void
725 param_value_array_finalize (GParamSpec *pspec)
726 {
727   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
728   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_VALUE_ARRAY));
729
730   if (aspec->element_spec)
731     {
732       g_param_spec_unref (aspec->element_spec);
733       aspec->element_spec = NULL;
734     }
735
736   parent_class->finalize (pspec);
737 }
738
739 static void
740 param_value_array_set_default (GParamSpec *pspec,
741                                GValue     *value)
742 {
743   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
744
745   g_return_if_fail (value->data[0].v_pointer != NULL);  /* paranoid */
746   
747   /* g_value_reset (value);  already done */
748   value_array_ensure_size (value->data[0].v_pointer, aspec->fixed_n_elements);
749 }
750
751 static gboolean
752 param_value_array_validate (GParamSpec *pspec,
753                             GValue     *value)
754 {
755   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
756   GValueArray *value_array = value->data[0].v_pointer;
757   guint changed = 0;
758
759   g_return_val_if_fail (value->data[0].v_pointer != NULL, FALSE);       /* paranoid */
760
761   /* ensure array size validity */
762   changed += value_array_ensure_size (value_array, aspec->fixed_n_elements);
763
764   /* ensure array values validity against a present element spec */
765   if (aspec->element_spec)
766     {
767       GParamSpec *element_spec = aspec->element_spec;
768       guint i;
769
770       for (i = 0; i < value_array->n_values; i++)
771         {
772           GValue *element = value_array->values + i;
773
774           /* need to fixup value type, or ensure that the array value is initialized at all */
775           if (!g_value_type_compatible (G_VALUE_TYPE (element), G_PARAM_SPEC_VALUE_TYPE (element_spec)))
776             {
777               if (G_VALUE_TYPE (element) != 0)
778                 g_value_unset (element);
779               g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec));
780               g_param_value_set_default (element_spec, element);
781               changed++;
782             }
783           /* validate array value against element_spec */
784           changed += g_param_value_validate (element_spec, element);
785         }
786     }
787
788   return changed;
789 }
790
791 static gint
792 param_value_array_values_cmp (GParamSpec   *pspec,
793                               const GValue *value1,
794                               const GValue *value2)
795 {
796   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
797   GValueArray *value_array1 = value1->data[0].v_pointer;
798   GValueArray *value_array2 = value2->data[0].v_pointer;
799
800   g_return_val_if_fail (value1->data[0].v_pointer != NULL, -1); /* paranoid */
801   g_return_val_if_fail (value2->data[0].v_pointer != NULL, 1);  /* paranoid */
802
803   if (value_array1->n_values != value_array2->n_values)
804     return value_array1->n_values < value_array2->n_values ? -1 : 1;
805   else if (!aspec->element_spec)
806     {
807       /* we need an element specification for comparisons, so there's not much
808        * to compare here, try to at least provide stable lesser/greater result
809        */
810       return value_array1->n_values < value_array2->n_values ? -1 : value_array1->n_values > value_array2->n_values;
811     }
812   else /* value_array1->n_values == value_array2->n_values */
813     {
814       guint i;
815
816       for (i = 0; i < value_array1->n_values; i++)
817         {
818           GValue *element1 = value_array1->values + i;
819           GValue *element2 = value_array2->values + i;
820           gint cmp;
821
822           /* need corresponding element types, provide stable result otherwise */
823           if (G_VALUE_TYPE (element1) != G_VALUE_TYPE (element2))
824             return G_VALUE_TYPE (element1) < G_VALUE_TYPE (element2) ? -1 : 1;
825           cmp = g_param_values_cmp (aspec->element_spec, element1, element2);
826           if (cmp)
827             return cmp;
828         }
829       return 0;
830     }
831 }
832
833 static void
834 param_object_init (GParamSpec *pspec)
835 {
836   /* GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec); */
837 }
838
839 static void
840 param_object_set_default (GParamSpec *pspec,
841                           GValue     *value)
842 {
843   value->data[0].v_pointer = NULL;
844 }
845
846 static gboolean
847 param_object_validate (GParamSpec *pspec,
848                        GValue     *value)
849 {
850   GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
851   GObject *object = value->data[0].v_pointer;
852   guint changed = 0;
853   
854   if (object && !g_value_type_compatible (G_OBJECT_TYPE (object), G_PARAM_SPEC_VALUE_TYPE (ospec)))
855     {
856       g_object_unref (object);
857       value->data[0].v_pointer = NULL;
858       changed++;
859     }
860   
861   return changed;
862 }
863
864 static gint
865 param_object_values_cmp (GParamSpec   *pspec,
866                          const GValue *value1,
867                          const GValue *value2)
868 {
869   guint8 *p1 = value1->data[0].v_pointer;
870   guint8 *p2 = value2->data[0].v_pointer;
871
872   /* not much to compare here, try to at least provide stable lesser/greater result */
873
874   return p1 < p2 ? -1 : p1 > p2;
875 }
876
877
878 /* --- type initialization --- */
879 void
880 g_param_spec_types_init (void)  /* sync with gtype.c */
881 {
882   GType type;
883   
884   /* G_TYPE_PARAM_CHAR
885    */
886   {
887     static const GParamSpecTypeInfo pspec_info = {
888       sizeof (GParamSpecChar),  /* instance_size */
889       16,                       /* n_preallocs */
890       param_char_init,          /* instance_init */
891       G_TYPE_CHAR,              /* value_type */
892       NULL,                     /* finalize */
893       param_char_set_default,   /* value_set_default */
894       param_char_validate,      /* value_validate */
895       param_int_values_cmp,     /* values_cmp */
896     };
897     type = g_param_type_register_static ("GParamChar", &pspec_info);
898     g_assert (type == G_TYPE_PARAM_CHAR);
899   }
900   
901   /* G_TYPE_PARAM_UCHAR
902    */
903   {
904     static const GParamSpecTypeInfo pspec_info = {
905       sizeof (GParamSpecUChar), /* instance_size */
906       16,                       /* n_preallocs */
907       param_uchar_init,         /* instance_init */
908       G_TYPE_UCHAR,             /* value_type */
909       NULL,                     /* finalize */
910       param_uchar_set_default,  /* value_set_default */
911       param_uchar_validate,     /* value_validate */
912       param_uint_values_cmp,    /* values_cmp */
913     };
914     type = g_param_type_register_static ("GParamUChar", &pspec_info);
915     g_assert (type == G_TYPE_PARAM_UCHAR);
916   }
917   
918   /* G_TYPE_PARAM_BOOLEAN
919    */
920   {
921     static const GParamSpecTypeInfo pspec_info = {
922       sizeof (GParamSpecBoolean), /* instance_size */
923       16,                         /* n_preallocs */
924       NULL,                       /* instance_init */
925       G_TYPE_BOOLEAN,             /* value_type */
926       NULL,                       /* finalize */
927       param_boolean_set_default,  /* value_set_default */
928       param_boolean_validate,     /* value_validate */
929       param_int_values_cmp,       /* values_cmp */
930     };
931     type = g_param_type_register_static ("GParamBoolean", &pspec_info);
932     g_assert (type == G_TYPE_PARAM_BOOLEAN);
933   }
934   
935   /* G_TYPE_PARAM_INT
936    */
937   {
938     static const GParamSpecTypeInfo pspec_info = {
939       sizeof (GParamSpecInt),   /* instance_size */
940       16,                       /* n_preallocs */
941       param_int_init,           /* instance_init */
942       G_TYPE_INT,               /* value_type */
943       NULL,                     /* finalize */
944       param_int_set_default,    /* value_set_default */
945       param_int_validate,       /* value_validate */
946       param_int_values_cmp,     /* values_cmp */
947     };
948     type = g_param_type_register_static ("GParamInt", &pspec_info);
949     g_assert (type == G_TYPE_PARAM_INT);
950   }
951   
952   /* G_TYPE_PARAM_UINT
953    */
954   {
955     static const GParamSpecTypeInfo pspec_info = {
956       sizeof (GParamSpecUInt),  /* instance_size */
957       16,                       /* n_preallocs */
958       param_uint_init,          /* instance_init */
959       G_TYPE_UINT,              /* value_type */
960       NULL,                     /* finalize */
961       param_uint_set_default,   /* value_set_default */
962       param_uint_validate,      /* value_validate */
963       param_uint_values_cmp,    /* values_cmp */
964     };
965     type = g_param_type_register_static ("GParamUInt", &pspec_info);
966     g_assert (type == G_TYPE_PARAM_UINT);
967   }
968   
969   /* G_TYPE_PARAM_LONG
970    */
971   {
972     static const GParamSpecTypeInfo pspec_info = {
973       sizeof (GParamSpecLong),  /* instance_size */
974       16,                       /* n_preallocs */
975       param_long_init,          /* instance_init */
976       G_TYPE_LONG,              /* value_type */
977       NULL,                     /* finalize */
978       param_long_set_default,   /* value_set_default */
979       param_long_validate,      /* value_validate */
980       param_long_values_cmp,    /* values_cmp */
981     };
982     type = g_param_type_register_static ("GParamLong", &pspec_info);
983     g_assert (type == G_TYPE_PARAM_LONG);
984   }
985   
986   /* G_TYPE_PARAM_ULONG
987    */
988   {
989     static const GParamSpecTypeInfo pspec_info = {
990       sizeof (GParamSpecULong), /* instance_size */
991       16,                       /* n_preallocs */
992       param_ulong_init,         /* instance_init */
993       G_TYPE_ULONG,             /* value_type */
994       NULL,                     /* finalize */
995       param_ulong_set_default,  /* value_set_default */
996       param_ulong_validate,     /* value_validate */
997       param_ulong_values_cmp,   /* values_cmp */
998     };
999     type = g_param_type_register_static ("GParamULong", &pspec_info);
1000     g_assert (type == G_TYPE_PARAM_ULONG);
1001   }
1002   
1003   /* G_TYPE_PARAM_ENUM
1004    */
1005   {
1006     static const GParamSpecTypeInfo pspec_info = {
1007       sizeof (GParamSpecEnum),  /* instance_size */
1008       16,                       /* n_preallocs */
1009       param_enum_init,          /* instance_init */
1010       G_TYPE_ENUM,              /* value_type */
1011       param_enum_finalize,      /* finalize */
1012       param_enum_set_default,   /* value_set_default */
1013       param_enum_validate,      /* value_validate */
1014       param_long_values_cmp,    /* values_cmp */
1015     };
1016     type = g_param_type_register_static ("GParamEnum", &pspec_info);
1017     g_assert (type == G_TYPE_PARAM_ENUM);
1018   }
1019   
1020   /* G_TYPE_PARAM_FLAGS
1021    */
1022   {
1023     static const GParamSpecTypeInfo pspec_info = {
1024       sizeof (GParamSpecFlags), /* instance_size */
1025       16,                       /* n_preallocs */
1026       param_flags_init,         /* instance_init */
1027       G_TYPE_FLAGS,             /* value_type */
1028       param_flags_finalize,     /* finalize */
1029       param_flags_set_default,  /* value_set_default */
1030       param_flags_validate,     /* value_validate */
1031       param_ulong_values_cmp,   /* values_cmp */
1032     };
1033     type = g_param_type_register_static ("GParamFlags", &pspec_info);
1034     g_assert (type == G_TYPE_PARAM_FLAGS);
1035   }
1036   
1037   /* G_TYPE_PARAM_FLOAT
1038    */
1039   {
1040     static const GParamSpecTypeInfo pspec_info = {
1041       sizeof (GParamSpecFloat), /* instance_size */
1042       16,                       /* n_preallocs */
1043       param_float_init,         /* instance_init */
1044       G_TYPE_FLOAT,             /* value_type */
1045       NULL,                     /* finalize */
1046       param_float_set_default,  /* value_set_default */
1047       param_float_validate,     /* value_validate */
1048       param_float_values_cmp,   /* values_cmp */
1049     };
1050     type = g_param_type_register_static ("GParamFloat", &pspec_info);
1051     g_assert (type == G_TYPE_PARAM_FLOAT);
1052   }
1053   
1054   /* G_TYPE_PARAM_DOUBLE
1055    */
1056   {
1057     static const GParamSpecTypeInfo pspec_info = {
1058       sizeof (GParamSpecDouble),        /* instance_size */
1059       16,                               /* n_preallocs */
1060       param_double_init,                /* instance_init */
1061       G_TYPE_DOUBLE,                    /* value_type */
1062       NULL,                             /* finalize */
1063       param_double_set_default,         /* value_set_default */
1064       param_double_validate,            /* value_validate */
1065       param_double_values_cmp,          /* values_cmp */
1066     };
1067     type = g_param_type_register_static ("GParamDouble", &pspec_info);
1068     g_assert (type == G_TYPE_PARAM_DOUBLE);
1069   }
1070   
1071   /* G_TYPE_PARAM_STRING
1072    */
1073   {
1074     static const GParamSpecTypeInfo pspec_info = {
1075       sizeof (GParamSpecString),        /* instance_size */
1076       16,                               /* n_preallocs */
1077       param_string_init,                /* instance_init */
1078       G_TYPE_STRING,                    /* value_type */
1079       param_string_finalize,            /* finalize */
1080       param_string_set_default,         /* value_set_default */
1081       param_string_validate,            /* value_validate */
1082       param_string_values_cmp,          /* values_cmp */
1083     };
1084     type = g_param_type_register_static ("GParamString", &pspec_info);
1085     g_assert (type == G_TYPE_PARAM_STRING);
1086   }
1087   
1088   /* G_TYPE_PARAM_PARAM
1089    */
1090   {
1091     static const GParamSpecTypeInfo pspec_info = {
1092       sizeof (GParamSpecParam), /* instance_size */
1093       16,                       /* n_preallocs */
1094       param_param_init,         /* instance_init */
1095       G_TYPE_PARAM,             /* value_type */
1096       NULL,                     /* finalize */
1097       param_param_set_default,  /* value_set_default */
1098       param_param_validate,     /* value_validate */
1099       param_pointer_values_cmp, /* values_cmp */
1100     };
1101     type = g_param_type_register_static ("GParamParam", &pspec_info);
1102     g_assert (type == G_TYPE_PARAM_PARAM);
1103   }
1104   
1105   /* G_TYPE_PARAM_BOXED
1106    */
1107   {
1108     static const GParamSpecTypeInfo pspec_info = {
1109       sizeof (GParamSpecBoxed), /* instance_size */
1110       4,                        /* n_preallocs */
1111       param_boxed_init,         /* instance_init */
1112       G_TYPE_BOXED,             /* value_type */
1113       NULL,                     /* finalize */
1114       param_boxed_set_default,  /* value_set_default */
1115       param_boxed_validate,     /* value_validate */
1116       param_boxed_values_cmp,   /* values_cmp */
1117     };
1118     type = g_param_type_register_static ("GParamBoxed", &pspec_info);
1119     g_assert (type == G_TYPE_PARAM_BOXED);
1120   }
1121
1122   /* G_TYPE_PARAM_POINTER
1123    */
1124   {
1125     static const GParamSpecTypeInfo pspec_info = {
1126       sizeof (GParamSpecPointer),  /* instance_size */
1127       0,                           /* n_preallocs */
1128       param_pointer_init,          /* instance_init */
1129       G_TYPE_POINTER,              /* value_type */
1130       NULL,                        /* finalize */
1131       param_pointer_set_default,   /* value_set_default */
1132       param_pointer_validate,      /* value_validate */
1133       param_pointer_values_cmp,    /* values_cmp */
1134     };
1135     type = g_param_type_register_static ("GParamPointer", &pspec_info);
1136     g_assert (type == G_TYPE_PARAM_POINTER);
1137   }
1138   
1139   /* G_TYPE_PARAM_VALUE_ARRAY
1140    */
1141   {
1142     static const GParamSpecTypeInfo pspec_info = {
1143       sizeof (GParamSpecValueArray),    /* instance_size */
1144       0,                                /* n_preallocs */
1145       param_value_array_init,           /* instance_init */
1146       G_TYPE_VALUE_ARRAY,               /* value_type */
1147       param_value_array_finalize,       /* finalize */
1148       param_value_array_set_default,    /* value_set_default */
1149       param_value_array_validate,       /* value_validate */
1150       param_value_array_values_cmp,     /* values_cmp */
1151     };
1152     type = g_param_type_register_static ("GParamValueArray", &pspec_info);
1153     g_assert (type == G_TYPE_PARAM_VALUE_ARRAY);
1154   }
1155
1156   /* G_TYPE_PARAM_CLOSURE
1157    */
1158   {
1159     static const GParamSpecTypeInfo pspec_info = {
1160       sizeof (GParamSpecClosure),   /* instance_size */
1161       0,                            /* n_preallocs */
1162       param_closure_init,           /* instance_init */
1163       G_TYPE_CLOSURE,               /* value_type */
1164       NULL,                         /* finalize */
1165       param_closure_set_default,    /* value_set_default */
1166       param_closure_validate,       /* value_validate */
1167       param_closure_values_cmp,     /* values_cmp */
1168     };
1169     type = g_param_type_register_static ("GParamClosure", &pspec_info);
1170     g_assert (type == G_TYPE_PARAM_CLOSURE);
1171   }
1172   
1173   /* G_TYPE_PARAM_OBJECT
1174    */
1175   {
1176     static const GParamSpecTypeInfo pspec_info = {
1177       sizeof (GParamSpecObject), /* instance_size */
1178       16,                        /* n_preallocs */
1179       param_object_init,         /* instance_init */
1180       G_TYPE_OBJECT,             /* value_type */
1181       NULL,                      /* finalize */
1182       param_object_set_default,  /* value_set_default */
1183       param_object_validate,     /* value_validate */
1184       param_object_values_cmp,   /* values_cmp */
1185     };
1186     type = g_param_type_register_static ("GParamObject", &pspec_info);
1187     g_assert (type == G_TYPE_PARAM_OBJECT);
1188   }
1189 }
1190
1191
1192 /* --- GParamSpec initialization --- */
1193 GParamSpec*
1194 g_param_spec_char (const gchar *name,
1195                    const gchar *nick,
1196                    const gchar *blurb,
1197                    gint8        minimum,
1198                    gint8        maximum,
1199                    gint8        default_value,
1200                    GParamFlags  flags)
1201 {
1202   GParamSpecChar *cspec = g_param_spec_internal (G_TYPE_PARAM_CHAR,
1203                                                  name,
1204                                                  nick,
1205                                                  blurb,
1206                                                  flags);
1207   
1208   cspec->minimum = minimum;
1209   cspec->maximum = maximum;
1210   cspec->default_value = default_value;
1211   
1212   return G_PARAM_SPEC (cspec);
1213 }
1214
1215 GParamSpec*
1216 g_param_spec_uchar (const gchar *name,
1217                     const gchar *nick,
1218                     const gchar *blurb,
1219                     guint8       minimum,
1220                     guint8       maximum,
1221                     guint8       default_value,
1222                     GParamFlags  flags)
1223 {
1224   GParamSpecUChar *uspec = g_param_spec_internal (G_TYPE_PARAM_UCHAR,
1225                                                   name,
1226                                                   nick,
1227                                                   blurb,
1228                                                   flags);
1229   
1230   uspec->minimum = minimum;
1231   uspec->maximum = maximum;
1232   uspec->default_value = default_value;
1233   
1234   return G_PARAM_SPEC (uspec);
1235 }
1236
1237 GParamSpec*
1238 g_param_spec_boolean (const gchar *name,
1239                       const gchar *nick,
1240                       const gchar *blurb,
1241                       gboolean     default_value,
1242                       GParamFlags  flags)
1243 {
1244   GParamSpecBoolean *bspec = g_param_spec_internal (G_TYPE_PARAM_BOOLEAN,
1245                                                     name,
1246                                                     nick,
1247                                                     blurb,
1248                                                     flags);
1249   
1250   bspec->default_value = default_value;
1251   
1252   return G_PARAM_SPEC (bspec);
1253 }
1254
1255 GParamSpec*
1256 g_param_spec_int (const gchar *name,
1257                   const gchar *nick,
1258                   const gchar *blurb,
1259                   gint         minimum,
1260                   gint         maximum,
1261                   gint         default_value,
1262                   GParamFlags  flags)
1263 {
1264   GParamSpecInt *ispec = g_param_spec_internal (G_TYPE_PARAM_INT,
1265                                                 name,
1266                                                 nick,
1267                                                 blurb,
1268                                                 flags);
1269   
1270   ispec->minimum = minimum;
1271   ispec->maximum = maximum;
1272   ispec->default_value = default_value;
1273   
1274   return G_PARAM_SPEC (ispec);
1275 }
1276
1277 GParamSpec*
1278 g_param_spec_uint (const gchar *name,
1279                    const gchar *nick,
1280                    const gchar *blurb,
1281                    guint        minimum,
1282                    guint        maximum,
1283                    guint        default_value,
1284                    GParamFlags  flags)
1285 {
1286   GParamSpecUInt *uspec = g_param_spec_internal (G_TYPE_PARAM_UINT,
1287                                                  name,
1288                                                  nick,
1289                                                  blurb,
1290                                                  flags);
1291   
1292   uspec->minimum = minimum;
1293   uspec->maximum = maximum;
1294   uspec->default_value = default_value;
1295   
1296   return G_PARAM_SPEC (uspec);
1297 }
1298
1299 GParamSpec*
1300 g_param_spec_long (const gchar *name,
1301                    const gchar *nick,
1302                    const gchar *blurb,
1303                    glong        minimum,
1304                    glong        maximum,
1305                    glong        default_value,
1306                    GParamFlags  flags)
1307 {
1308   GParamSpecLong *lspec = g_param_spec_internal (G_TYPE_PARAM_LONG,
1309                                                  name,
1310                                                  nick,
1311                                                  blurb,
1312                                                  flags);
1313   
1314   lspec->minimum = minimum;
1315   lspec->maximum = maximum;
1316   lspec->default_value = default_value;
1317   
1318   return G_PARAM_SPEC (lspec);
1319 }
1320
1321 GParamSpec*
1322 g_param_spec_ulong (const gchar *name,
1323                     const gchar *nick,
1324                     const gchar *blurb,
1325                     gulong       minimum,
1326                     gulong       maximum,
1327                     gulong       default_value,
1328                     GParamFlags  flags)
1329 {
1330   GParamSpecULong *uspec = g_param_spec_internal (G_TYPE_PARAM_ULONG,
1331                                                   name,
1332                                                   nick,
1333                                                   blurb,
1334                                                   flags);
1335   
1336   uspec->minimum = minimum;
1337   uspec->maximum = maximum;
1338   uspec->default_value = default_value;
1339   
1340   return G_PARAM_SPEC (uspec);
1341 }
1342
1343 GParamSpec*
1344 g_param_spec_enum (const gchar *name,
1345                    const gchar *nick,
1346                    const gchar *blurb,
1347                    GType        enum_type,
1348                    gint         default_value,
1349                    GParamFlags  flags)
1350 {
1351   GParamSpecEnum *espec;
1352   
1353   g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
1354   
1355   espec = g_param_spec_internal (G_TYPE_PARAM_ENUM,
1356                                  name,
1357                                  nick,
1358                                  blurb,
1359                                  flags);
1360   
1361   espec->enum_class = g_type_class_ref (enum_type);
1362   espec->default_value = default_value;
1363   G_PARAM_SPEC (espec)->value_type = enum_type;
1364   
1365   return G_PARAM_SPEC (espec);
1366 }
1367
1368 GParamSpec*
1369 g_param_spec_flags (const gchar *name,
1370                     const gchar *nick,
1371                     const gchar *blurb,
1372                     GType        flags_type,
1373                     guint        default_value,
1374                     GParamFlags  flags)
1375 {
1376   GParamSpecFlags *fspec;
1377   
1378   g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), NULL);
1379   
1380   fspec = g_param_spec_internal (G_TYPE_PARAM_FLAGS,
1381                                  name,
1382                                  nick,
1383                                  blurb,
1384                                  flags);
1385   
1386   fspec->flags_class = g_type_class_ref (flags_type);
1387   fspec->default_value = default_value;
1388   G_PARAM_SPEC (fspec)->value_type = flags_type;
1389   
1390   return G_PARAM_SPEC (fspec);
1391 }
1392
1393 GParamSpec*
1394 g_param_spec_float (const gchar *name,
1395                     const gchar *nick,
1396                     const gchar *blurb,
1397                     gfloat       minimum,
1398                     gfloat       maximum,
1399                     gfloat       default_value,
1400                     GParamFlags  flags)
1401 {
1402   GParamSpecFloat *fspec = g_param_spec_internal (G_TYPE_PARAM_FLOAT,
1403                                                   name,
1404                                                   nick,
1405                                                   blurb,
1406                                                   flags);
1407   
1408   fspec->minimum = minimum;
1409   fspec->maximum = maximum;
1410   fspec->default_value = default_value;
1411   
1412   return G_PARAM_SPEC (fspec);
1413 }
1414
1415 GParamSpec*
1416 g_param_spec_double (const gchar *name,
1417                      const gchar *nick,
1418                      const gchar *blurb,
1419                      gdouble      minimum,
1420                      gdouble      maximum,
1421                      gdouble      default_value,
1422                      GParamFlags  flags)
1423 {
1424   GParamSpecDouble *dspec = g_param_spec_internal (G_TYPE_PARAM_DOUBLE,
1425                                                    name,
1426                                                    nick,
1427                                                    blurb,
1428                                                    flags);
1429   
1430   dspec->minimum = minimum;
1431   dspec->maximum = maximum;
1432   dspec->default_value = default_value;
1433   
1434   return G_PARAM_SPEC (dspec);
1435 }
1436
1437 GParamSpec*
1438 g_param_spec_string (const gchar *name,
1439                      const gchar *nick,
1440                      const gchar *blurb,
1441                      const gchar *default_value,
1442                      GParamFlags  flags)
1443 {
1444   GParamSpecString *sspec = g_param_spec_internal (G_TYPE_PARAM_STRING,
1445                                                    name,
1446                                                    nick,
1447                                                    blurb,
1448                                                    flags);
1449   g_free (sspec->default_value);
1450   sspec->default_value = g_strdup (default_value);
1451   
1452   return G_PARAM_SPEC (sspec);
1453 }
1454
1455 GParamSpec*
1456 g_param_spec_stringc (const gchar *name,
1457                       const gchar *nick,
1458                       const gchar *blurb,
1459                       const gchar *default_value,
1460                       GParamFlags  flags)
1461 {
1462   GParamSpecString *sspec = g_param_spec_internal (G_TYPE_PARAM_STRING,
1463                                                    name,
1464                                                    nick,
1465                                                    blurb,
1466                                                    flags);
1467   g_free (sspec->default_value);
1468   sspec->default_value = g_strdup (default_value);
1469   g_free (sspec->cset_first);
1470   sspec->cset_first = g_strdup (G_CSET_a_2_z "_" G_CSET_A_2_Z);
1471   g_free (sspec->cset_nth);
1472   sspec->cset_nth = g_strdup (G_CSET_a_2_z
1473                               "_0123456789"
1474                               /* G_CSET_LATINS G_CSET_LATINC */
1475                               G_CSET_A_2_Z);
1476   
1477   return G_PARAM_SPEC (sspec);
1478 }
1479
1480 GParamSpec*
1481 g_param_spec_param (const gchar *name,
1482                     const gchar *nick,
1483                     const gchar *blurb,
1484                     GType        param_type,
1485                     GParamFlags  flags)
1486 {
1487   GParamSpecParam *pspec;
1488   
1489   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type), NULL);
1490   
1491   pspec = g_param_spec_internal (G_TYPE_PARAM_PARAM,
1492                                  name,
1493                                  nick,
1494                                  blurb,
1495                                  flags);
1496   G_PARAM_SPEC (pspec)->value_type = param_type;
1497   
1498   return G_PARAM_SPEC (pspec);
1499 }
1500
1501 GParamSpec*
1502 g_param_spec_boxed (const gchar *name,
1503                     const gchar *nick,
1504                     const gchar *blurb,
1505                     GType        boxed_type,
1506                     GParamFlags  flags)
1507 {
1508   GParamSpecBoxed *bspec;
1509   
1510   g_return_val_if_fail (G_TYPE_IS_BOXED (boxed_type), NULL);
1511   g_return_val_if_fail (G_TYPE_IS_DERIVED (boxed_type), NULL);
1512   
1513   bspec = g_param_spec_internal (G_TYPE_PARAM_BOXED,
1514                                  name,
1515                                  nick,
1516                                  blurb,
1517                                  flags);
1518   G_PARAM_SPEC (bspec)->value_type = boxed_type;
1519   
1520   return G_PARAM_SPEC (bspec);
1521 }
1522
1523 GParamSpec*
1524 g_param_spec_pointer (const gchar *name,
1525                       const gchar *nick,
1526                       const gchar *blurb,
1527                       GParamFlags  flags)
1528 {
1529   GParamSpecPointer *pspec;
1530   
1531   pspec = g_param_spec_internal (G_TYPE_PARAM_POINTER,
1532                                  name,
1533                                  nick,
1534                                  blurb,
1535                                  flags);
1536   return G_PARAM_SPEC (pspec);
1537 }
1538
1539 GParamSpec*
1540 g_param_spec_value_array (const gchar *name,
1541                           const gchar *nick,
1542                           const gchar *blurb,
1543                           GParamSpec  *element_spec,
1544                           GParamFlags  flags)
1545 {
1546   GParamSpecValueArray *aspec;
1547   
1548   if (element_spec)
1549     g_return_val_if_fail (G_IS_PARAM_SPEC (element_spec), NULL);
1550   
1551   aspec = g_param_spec_internal (G_TYPE_PARAM_VALUE_ARRAY,
1552                                  name,
1553                                  nick,
1554                                  blurb,
1555                                  flags);
1556   if (element_spec)
1557     {
1558       aspec->element_spec = g_param_spec_ref (element_spec);
1559       g_param_spec_sink (element_spec);
1560     }
1561
1562   return G_PARAM_SPEC (aspec);
1563 }
1564
1565 GParamSpec*
1566 g_param_spec_closure (const gchar *name,
1567                       const gchar *nick,
1568                       const gchar *blurb,
1569                       GParamFlags  flags)
1570 {
1571   GParamSpecClosure *cspec;
1572   
1573   cspec = g_param_spec_internal (G_TYPE_PARAM_CLOSURE,
1574                                  name,
1575                                  nick,
1576                                  blurb,
1577                                  flags);
1578   return G_PARAM_SPEC (cspec);
1579 }
1580
1581 GParamSpec*
1582 g_param_spec_object (const gchar *name,
1583                      const gchar *nick,
1584                      const gchar *blurb,
1585                      GType        object_type,
1586                      GParamFlags  flags)
1587 {
1588   GParamSpecObject *ospec;
1589   
1590   g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT), NULL);
1591   
1592   ospec = g_param_spec_internal (G_TYPE_PARAM_OBJECT,
1593                                  name,
1594                                  nick,
1595                                  blurb,
1596                                  flags);
1597   G_PARAM_SPEC (ospec)->value_type = object_type;
1598   
1599   return G_PARAM_SPEC (ospec);
1600 }