Fix crashes in various GParamSpec creation functions
[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  * Copyright (C) 2010 Christian Persch
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * MT safe
23  */
24
25 #include "config.h"
26
27 #include <string.h>
28
29 #define GLIB_DISABLE_DEPRECATION_WARNINGS
30
31 #include "gparamspecs.h"
32 #include "gtype-private.h"
33 #include "gvaluecollector.h"
34
35 #include "gvaluearray.h"
36
37
38 /**
39  * SECTION:param_value_types
40  * @short_description: Standard Parameter and Value Types
41  * @see_also: #GParamSpec, #GValue, g_object_class_install_property().
42  * @title: Parameters and Values
43  *
44  * #GValue provides an abstract container structure which can be
45  * copied, transformed and compared while holding a value of any
46  * (derived) type, which is registered as a #GType with a
47  * #GTypeValueTable in its #GTypeInfo structure.  Parameter
48  * specifications for most value types can be created as #GParamSpec
49  * derived instances, to implement e.g. #GObject properties which
50  * operate on #GValue containers.
51  *
52  * Parameter names need to start with a letter (a-z or A-Z). Subsequent
53  * characters can be letters, numbers or a '-'.
54  * All other characters are replaced by a '-' during construction.
55  */
56
57
58 #define G_FLOAT_EPSILON         (1e-30)
59 #define G_DOUBLE_EPSILON        (1e-90)
60
61
62 /* --- param spec functions --- */
63 static void
64 param_char_init (GParamSpec *pspec)
65 {
66   GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
67   
68   cspec->minimum = 0x7f;
69   cspec->maximum = 0x80;
70   cspec->default_value = 0;
71 }
72
73 static void
74 param_char_set_default (GParamSpec *pspec,
75                         GValue     *value)
76 {
77   value->data[0].v_int = G_PARAM_SPEC_CHAR (pspec)->default_value;
78 }
79
80 static gboolean
81 param_char_validate (GParamSpec *pspec,
82                      GValue     *value)
83 {
84   GParamSpecChar *cspec = G_PARAM_SPEC_CHAR (pspec);
85   gint oval = value->data[0].v_int;
86   
87   value->data[0].v_int = CLAMP (value->data[0].v_int, cspec->minimum, cspec->maximum);
88   
89   return value->data[0].v_int != oval;
90 }
91
92 static void
93 param_uchar_init (GParamSpec *pspec)
94 {
95   GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
96   
97   uspec->minimum = 0;
98   uspec->maximum = 0xff;
99   uspec->default_value = 0;
100 }
101
102 static void
103 param_uchar_set_default (GParamSpec *pspec,
104                          GValue     *value)
105 {
106   value->data[0].v_uint = G_PARAM_SPEC_UCHAR (pspec)->default_value;
107 }
108
109 static gboolean
110 param_uchar_validate (GParamSpec *pspec,
111                       GValue     *value)
112 {
113   GParamSpecUChar *uspec = G_PARAM_SPEC_UCHAR (pspec);
114   guint oval = value->data[0].v_uint;
115   
116   value->data[0].v_uint = CLAMP (value->data[0].v_uint, uspec->minimum, uspec->maximum);
117   
118   return value->data[0].v_uint != oval;
119 }
120
121 static void
122 param_boolean_set_default (GParamSpec *pspec,
123                            GValue     *value)
124 {
125   value->data[0].v_int = G_PARAM_SPEC_BOOLEAN (pspec)->default_value;
126 }
127
128 static gboolean
129 param_boolean_validate (GParamSpec *pspec,
130                         GValue     *value)
131 {
132   gint oval = value->data[0].v_int;
133   
134   value->data[0].v_int = value->data[0].v_int != FALSE;
135   
136   return value->data[0].v_int != oval;
137 }
138
139 static void
140 param_int_init (GParamSpec *pspec)
141 {
142   GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
143   
144   ispec->minimum = 0x7fffffff;
145   ispec->maximum = 0x80000000;
146   ispec->default_value = 0;
147 }
148
149 static void
150 param_int_set_default (GParamSpec *pspec,
151                        GValue     *value)
152 {
153   value->data[0].v_int = G_PARAM_SPEC_INT (pspec)->default_value;
154 }
155
156 static gboolean
157 param_int_validate (GParamSpec *pspec,
158                     GValue     *value)
159 {
160   GParamSpecInt *ispec = G_PARAM_SPEC_INT (pspec);
161   gint oval = value->data[0].v_int;
162   
163   value->data[0].v_int = CLAMP (value->data[0].v_int, ispec->minimum, ispec->maximum);
164   
165   return value->data[0].v_int != oval;
166 }
167
168 static gint
169 param_int_values_cmp (GParamSpec   *pspec,
170                       const GValue *value1,
171                       const GValue *value2)
172 {
173   if (value1->data[0].v_int < value2->data[0].v_int)
174     return -1;
175   else
176     return value1->data[0].v_int > value2->data[0].v_int;
177 }
178
179 static void
180 param_uint_init (GParamSpec *pspec)
181 {
182   GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
183   
184   uspec->minimum = 0;
185   uspec->maximum = 0xffffffff;
186   uspec->default_value = 0;
187 }
188
189 static void
190 param_uint_set_default (GParamSpec *pspec,
191                         GValue     *value)
192 {
193   value->data[0].v_uint = G_PARAM_SPEC_UINT (pspec)->default_value;
194 }
195
196 static gboolean
197 param_uint_validate (GParamSpec *pspec,
198                      GValue     *value)
199 {
200   GParamSpecUInt *uspec = G_PARAM_SPEC_UINT (pspec);
201   guint oval = value->data[0].v_uint;
202   
203   value->data[0].v_uint = CLAMP (value->data[0].v_uint, uspec->minimum, uspec->maximum);
204   
205   return value->data[0].v_uint != oval;
206 }
207
208 static gint
209 param_uint_values_cmp (GParamSpec   *pspec,
210                        const GValue *value1,
211                        const GValue *value2)
212 {
213   if (value1->data[0].v_uint < value2->data[0].v_uint)
214     return -1;
215   else
216     return value1->data[0].v_uint > value2->data[0].v_uint;
217 }
218
219 static void
220 param_long_init (GParamSpec *pspec)
221 {
222   GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
223   
224 #if SIZEOF_LONG == 4
225   lspec->minimum = 0x7fffffff;
226   lspec->maximum = 0x80000000;
227 #else /* SIZEOF_LONG != 4 (8) */
228   lspec->minimum = 0x7fffffffffffffff;
229   lspec->maximum = 0x8000000000000000;
230 #endif
231   lspec->default_value = 0;
232 }
233
234 static void
235 param_long_set_default (GParamSpec *pspec,
236                         GValue     *value)
237 {
238   value->data[0].v_long = G_PARAM_SPEC_LONG (pspec)->default_value;
239 }
240
241 static gboolean
242 param_long_validate (GParamSpec *pspec,
243                      GValue     *value)
244 {
245   GParamSpecLong *lspec = G_PARAM_SPEC_LONG (pspec);
246   glong oval = value->data[0].v_long;
247   
248   value->data[0].v_long = CLAMP (value->data[0].v_long, lspec->minimum, lspec->maximum);
249   
250   return value->data[0].v_long != oval;
251 }
252
253 static gint
254 param_long_values_cmp (GParamSpec   *pspec,
255                        const GValue *value1,
256                        const GValue *value2)
257 {
258   if (value1->data[0].v_long < value2->data[0].v_long)
259     return -1;
260   else
261     return value1->data[0].v_long > value2->data[0].v_long;
262 }
263
264 static void
265 param_ulong_init (GParamSpec *pspec)
266 {
267   GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
268   
269   uspec->minimum = 0;
270 #if SIZEOF_LONG == 4
271   uspec->maximum = 0xffffffff;
272 #else /* SIZEOF_LONG != 4 (8) */
273   uspec->maximum = 0xffffffffffffffff;
274 #endif
275   uspec->default_value = 0;
276 }
277
278 static void
279 param_ulong_set_default (GParamSpec *pspec,
280                          GValue     *value)
281 {
282   value->data[0].v_ulong = G_PARAM_SPEC_ULONG (pspec)->default_value;
283 }
284
285 static gboolean
286 param_ulong_validate (GParamSpec *pspec,
287                       GValue     *value)
288 {
289   GParamSpecULong *uspec = G_PARAM_SPEC_ULONG (pspec);
290   gulong oval = value->data[0].v_ulong;
291   
292   value->data[0].v_ulong = CLAMP (value->data[0].v_ulong, uspec->minimum, uspec->maximum);
293   
294   return value->data[0].v_ulong != oval;
295 }
296
297 static gint
298 param_ulong_values_cmp (GParamSpec   *pspec,
299                         const GValue *value1,
300                         const GValue *value2)
301 {
302   if (value1->data[0].v_ulong < value2->data[0].v_ulong)
303     return -1;
304   else
305     return value1->data[0].v_ulong > value2->data[0].v_ulong;
306 }
307
308 static void
309 param_int64_init (GParamSpec *pspec)
310 {
311   GParamSpecInt64 *lspec = G_PARAM_SPEC_INT64 (pspec);
312   
313   lspec->minimum = G_MININT64;
314   lspec->maximum = G_MAXINT64;
315   lspec->default_value = 0;
316 }
317
318 static void
319 param_int64_set_default (GParamSpec *pspec,
320                         GValue     *value)
321 {
322   value->data[0].v_int64 = G_PARAM_SPEC_INT64 (pspec)->default_value;
323 }
324
325 static gboolean
326 param_int64_validate (GParamSpec *pspec,
327                      GValue     *value)
328 {
329   GParamSpecInt64 *lspec = G_PARAM_SPEC_INT64 (pspec);
330   gint64 oval = value->data[0].v_int64;
331   
332   value->data[0].v_int64 = CLAMP (value->data[0].v_int64, lspec->minimum, lspec->maximum);
333   
334   return value->data[0].v_int64 != oval;
335 }
336
337 static gint
338 param_int64_values_cmp (GParamSpec   *pspec,
339                        const GValue *value1,
340                        const GValue *value2)
341 {
342   if (value1->data[0].v_int64 < value2->data[0].v_int64)
343     return -1;
344   else
345     return value1->data[0].v_int64 > value2->data[0].v_int64;
346 }
347
348 static void
349 param_uint64_init (GParamSpec *pspec)
350 {
351   GParamSpecUInt64 *uspec = G_PARAM_SPEC_UINT64 (pspec);
352   
353   uspec->minimum = 0;
354   uspec->maximum = G_MAXUINT64;
355   uspec->default_value = 0;
356 }
357
358 static void
359 param_uint64_set_default (GParamSpec *pspec,
360                          GValue     *value)
361 {
362   value->data[0].v_uint64 = G_PARAM_SPEC_UINT64 (pspec)->default_value;
363 }
364
365 static gboolean
366 param_uint64_validate (GParamSpec *pspec,
367                       GValue     *value)
368 {
369   GParamSpecUInt64 *uspec = G_PARAM_SPEC_UINT64 (pspec);
370   guint64 oval = value->data[0].v_uint64;
371   
372   value->data[0].v_uint64 = CLAMP (value->data[0].v_uint64, uspec->minimum, uspec->maximum);
373   
374   return value->data[0].v_uint64 != oval;
375 }
376
377 static gint
378 param_uint64_values_cmp (GParamSpec   *pspec,
379                         const GValue *value1,
380                         const GValue *value2)
381 {
382   if (value1->data[0].v_uint64 < value2->data[0].v_uint64)
383     return -1;
384   else
385     return value1->data[0].v_uint64 > value2->data[0].v_uint64;
386 }
387
388 static void
389 param_unichar_init (GParamSpec *pspec)
390 {
391   GParamSpecUnichar *uspec = G_PARAM_SPEC_UNICHAR (pspec);
392   
393   uspec->default_value = 0;
394 }
395
396 static void
397 param_unichar_set_default (GParamSpec *pspec,
398                          GValue     *value)
399 {
400   value->data[0].v_uint = G_PARAM_SPEC_UNICHAR (pspec)->default_value;
401 }
402
403 static gboolean
404 param_unichar_validate (GParamSpec *pspec,
405                         GValue     *value)
406 {
407   gunichar oval = value->data[0].v_uint;
408   gboolean changed = FALSE;
409
410   if (!g_unichar_validate (oval))
411     {
412       value->data[0].v_uint = 0;
413       changed = TRUE;
414     }
415
416   return changed;
417 }
418
419 static gint
420 param_unichar_values_cmp (GParamSpec   *pspec,
421                         const GValue *value1,
422                         const GValue *value2)
423 {
424   if (value1->data[0].v_uint < value2->data[0].v_uint)
425     return -1;
426   else
427     return value1->data[0].v_uint > value2->data[0].v_uint;
428 }
429
430 static void
431 param_enum_init (GParamSpec *pspec)
432 {
433   GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
434   
435   espec->enum_class = NULL;
436   espec->default_value = 0;
437 }
438
439 static void
440 param_enum_finalize (GParamSpec *pspec)
441 {
442   GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
443   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_ENUM));
444   
445   if (espec->enum_class)
446     {
447       g_type_class_unref (espec->enum_class);
448       espec->enum_class = NULL;
449     }
450   
451   parent_class->finalize (pspec);
452 }
453
454 static void
455 param_enum_set_default (GParamSpec *pspec,
456                         GValue     *value)
457 {
458   value->data[0].v_long = G_PARAM_SPEC_ENUM (pspec)->default_value;
459 }
460
461 static gboolean
462 param_enum_validate (GParamSpec *pspec,
463                      GValue     *value)
464 {
465   GParamSpecEnum *espec = G_PARAM_SPEC_ENUM (pspec);
466   glong oval = value->data[0].v_long;
467   
468   if (!espec->enum_class ||
469       !g_enum_get_value (espec->enum_class, value->data[0].v_long))
470     value->data[0].v_long = espec->default_value;
471   
472   return value->data[0].v_long != oval;
473 }
474
475 static void
476 param_flags_init (GParamSpec *pspec)
477 {
478   GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
479   
480   fspec->flags_class = NULL;
481   fspec->default_value = 0;
482 }
483
484 static void
485 param_flags_finalize (GParamSpec *pspec)
486 {
487   GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
488   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_FLAGS));
489   
490   if (fspec->flags_class)
491     {
492       g_type_class_unref (fspec->flags_class);
493       fspec->flags_class = NULL;
494     }
495   
496   parent_class->finalize (pspec);
497 }
498
499 static void
500 param_flags_set_default (GParamSpec *pspec,
501                          GValue     *value)
502 {
503   value->data[0].v_ulong = G_PARAM_SPEC_FLAGS (pspec)->default_value;
504 }
505
506 static gboolean
507 param_flags_validate (GParamSpec *pspec,
508                       GValue     *value)
509 {
510   GParamSpecFlags *fspec = G_PARAM_SPEC_FLAGS (pspec);
511   gulong oval = value->data[0].v_ulong;
512   
513   if (fspec->flags_class)
514     value->data[0].v_ulong &= fspec->flags_class->mask;
515   else
516     value->data[0].v_ulong = fspec->default_value;
517   
518   return value->data[0].v_ulong != oval;
519 }
520
521 static void
522 param_float_init (GParamSpec *pspec)
523 {
524   GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
525   
526   fspec->minimum = -G_MAXFLOAT;
527   fspec->maximum = G_MAXFLOAT;
528   fspec->default_value = 0;
529   fspec->epsilon = G_FLOAT_EPSILON;
530 }
531
532 static void
533 param_float_set_default (GParamSpec *pspec,
534                          GValue     *value)
535 {
536   value->data[0].v_float = G_PARAM_SPEC_FLOAT (pspec)->default_value;
537 }
538
539 static gboolean
540 param_float_validate (GParamSpec *pspec,
541                       GValue     *value)
542 {
543   GParamSpecFloat *fspec = G_PARAM_SPEC_FLOAT (pspec);
544   gfloat oval = value->data[0].v_float;
545   
546   value->data[0].v_float = CLAMP (value->data[0].v_float, fspec->minimum, fspec->maximum);
547   
548   return value->data[0].v_float != oval;
549 }
550
551 static gint
552 param_float_values_cmp (GParamSpec   *pspec,
553                         const GValue *value1,
554                         const GValue *value2)
555 {
556   gfloat epsilon = G_PARAM_SPEC_FLOAT (pspec)->epsilon;
557   
558   if (value1->data[0].v_float < value2->data[0].v_float)
559     return - (value2->data[0].v_float - value1->data[0].v_float > epsilon);
560   else
561     return value1->data[0].v_float - value2->data[0].v_float > epsilon;
562 }
563
564 static void
565 param_double_init (GParamSpec *pspec)
566 {
567   GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
568   
569   dspec->minimum = -G_MAXDOUBLE;
570   dspec->maximum = G_MAXDOUBLE;
571   dspec->default_value = 0;
572   dspec->epsilon = G_DOUBLE_EPSILON;
573 }
574
575 static void
576 param_double_set_default (GParamSpec *pspec,
577                           GValue     *value)
578 {
579   value->data[0].v_double = G_PARAM_SPEC_DOUBLE (pspec)->default_value;
580 }
581
582 static gboolean
583 param_double_validate (GParamSpec *pspec,
584                        GValue     *value)
585 {
586   GParamSpecDouble *dspec = G_PARAM_SPEC_DOUBLE (pspec);
587   gdouble oval = value->data[0].v_double;
588   
589   value->data[0].v_double = CLAMP (value->data[0].v_double, dspec->minimum, dspec->maximum);
590   
591   return value->data[0].v_double != oval;
592 }
593
594 static gint
595 param_double_values_cmp (GParamSpec   *pspec,
596                          const GValue *value1,
597                          const GValue *value2)
598 {
599   gdouble epsilon = G_PARAM_SPEC_DOUBLE (pspec)->epsilon;
600   
601   if (value1->data[0].v_double < value2->data[0].v_double)
602     return - (value2->data[0].v_double - value1->data[0].v_double > epsilon);
603   else
604     return value1->data[0].v_double - value2->data[0].v_double > epsilon;
605 }
606
607 static void
608 param_string_init (GParamSpec *pspec)
609 {
610   GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
611   
612   sspec->default_value = NULL;
613   sspec->cset_first = NULL;
614   sspec->cset_nth = NULL;
615   sspec->substitutor = '_';
616   sspec->null_fold_if_empty = FALSE;
617   sspec->ensure_non_null = FALSE;
618 }
619
620 static void
621 param_string_finalize (GParamSpec *pspec)
622 {
623   GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
624   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_STRING));
625   
626   g_free (sspec->default_value);
627   g_free (sspec->cset_first);
628   g_free (sspec->cset_nth);
629   sspec->default_value = NULL;
630   sspec->cset_first = NULL;
631   sspec->cset_nth = NULL;
632   
633   parent_class->finalize (pspec);
634 }
635
636 static void
637 param_string_set_default (GParamSpec *pspec,
638                           GValue     *value)
639 {
640   value->data[0].v_pointer = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
641 }
642
643 static gboolean
644 param_string_validate (GParamSpec *pspec,
645                        GValue     *value)
646 {
647   GParamSpecString *sspec = G_PARAM_SPEC_STRING (pspec);
648   gchar *string = value->data[0].v_pointer;
649   guint changed = 0;
650   
651   if (string && string[0])
652     {
653       gchar *s;
654       
655       if (sspec->cset_first && !strchr (sspec->cset_first, string[0]))
656         {
657           if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
658             {
659               value->data[0].v_pointer = g_strdup (string);
660               string = value->data[0].v_pointer;
661               value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
662             }
663           string[0] = sspec->substitutor;
664           changed++;
665         }
666       if (sspec->cset_nth)
667         for (s = string + 1; *s; s++)
668           if (!strchr (sspec->cset_nth, *s))
669             {
670               if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
671                 {
672                   value->data[0].v_pointer = g_strdup (string);
673                   s = (gchar*) value->data[0].v_pointer + (s - string);
674                   string = value->data[0].v_pointer;
675                   value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
676                 }
677               *s = sspec->substitutor;
678               changed++;
679             }
680     }
681   if (sspec->null_fold_if_empty && string && string[0] == 0)
682     {
683       if (!(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
684         g_free (value->data[0].v_pointer);
685       else
686         value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
687       value->data[0].v_pointer = NULL;
688       changed++;
689       string = value->data[0].v_pointer;
690     }
691   if (sspec->ensure_non_null && !string)
692     {
693       value->data[1].v_uint &= ~G_VALUE_NOCOPY_CONTENTS;
694       value->data[0].v_pointer = g_strdup ("");
695       changed++;
696       string = value->data[0].v_pointer;
697     }
698
699   return changed;
700 }
701
702 static gint
703 param_string_values_cmp (GParamSpec   *pspec,
704                          const GValue *value1,
705                          const GValue *value2)
706 {
707   if (!value1->data[0].v_pointer)
708     return value2->data[0].v_pointer != NULL ? -1 : 0;
709   else if (!value2->data[0].v_pointer)
710     return value1->data[0].v_pointer != NULL;
711   else
712     return strcmp (value1->data[0].v_pointer, value2->data[0].v_pointer);
713 }
714
715 static void
716 param_param_init (GParamSpec *pspec)
717 {
718   /* GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec); */
719 }
720
721 static void
722 param_param_set_default (GParamSpec *pspec,
723                          GValue     *value)
724 {
725   value->data[0].v_pointer = NULL;
726 }
727
728 static gboolean
729 param_param_validate (GParamSpec *pspec,
730                       GValue     *value)
731 {
732   /* GParamSpecParam *spec = G_PARAM_SPEC_PARAM (pspec); */
733   GParamSpec *param = value->data[0].v_pointer;
734   guint changed = 0;
735   
736   if (param && !g_value_type_compatible (G_PARAM_SPEC_TYPE (param), G_PARAM_SPEC_VALUE_TYPE (pspec)))
737     {
738       g_param_spec_unref (param);
739       value->data[0].v_pointer = NULL;
740       changed++;
741     }
742   
743   return changed;
744 }
745
746 static void
747 param_boxed_init (GParamSpec *pspec)
748 {
749   /* GParamSpecBoxed *bspec = G_PARAM_SPEC_BOXED (pspec); */
750 }
751
752 static void
753 param_boxed_set_default (GParamSpec *pspec,
754                          GValue     *value)
755 {
756   value->data[0].v_pointer = NULL;
757 }
758
759 static gboolean
760 param_boxed_validate (GParamSpec *pspec,
761                       GValue     *value)
762 {
763   /* GParamSpecBoxed *bspec = G_PARAM_SPEC_BOXED (pspec); */
764   guint changed = 0;
765
766   /* can't do a whole lot here since we haven't even G_BOXED_TYPE() */
767   
768   return changed;
769 }
770
771 static gint
772 param_boxed_values_cmp (GParamSpec    *pspec,
773                          const GValue *value1,
774                          const GValue *value2)
775 {
776   guint8 *p1 = value1->data[0].v_pointer;
777   guint8 *p2 = value2->data[0].v_pointer;
778
779   /* not much to compare here, try to at least provide stable lesser/greater result */
780
781   return p1 < p2 ? -1 : p1 > p2;
782 }
783
784 static void
785 param_pointer_init (GParamSpec *pspec)
786 {
787   /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
788 }
789
790 static void
791 param_pointer_set_default (GParamSpec *pspec,
792                            GValue     *value)
793 {
794   value->data[0].v_pointer = NULL;
795 }
796
797 static gboolean
798 param_pointer_validate (GParamSpec *pspec,
799                         GValue     *value)
800 {
801   /* GParamSpecPointer *spec = G_PARAM_SPEC_POINTER (pspec); */
802   guint changed = 0;
803   
804   return changed;
805 }
806
807 static gint
808 param_pointer_values_cmp (GParamSpec   *pspec,
809                           const GValue *value1,
810                           const GValue *value2)
811 {
812   guint8 *p1 = value1->data[0].v_pointer;
813   guint8 *p2 = value2->data[0].v_pointer;
814
815   /* not much to compare here, try to at least provide stable lesser/greater result */
816
817   return p1 < p2 ? -1 : p1 > p2;
818 }
819
820 static void
821 param_value_array_init (GParamSpec *pspec)
822 {
823   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
824
825   aspec->element_spec = NULL;
826   aspec->fixed_n_elements = 0; /* disable */
827 }
828
829 static inline guint
830 value_array_ensure_size (GValueArray *value_array,
831                          guint        fixed_n_elements)
832 {
833   guint changed = 0;
834
835   if (fixed_n_elements)
836     {
837       while (value_array->n_values < fixed_n_elements)
838         {
839           g_value_array_append (value_array, NULL);
840           changed++;
841         }
842       while (value_array->n_values > fixed_n_elements)
843         {
844           g_value_array_remove (value_array, value_array->n_values - 1);
845           changed++;
846         }
847     }
848   return changed;
849 }
850
851 static void
852 param_value_array_finalize (GParamSpec *pspec)
853 {
854   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
855   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_VALUE_ARRAY));
856
857   if (aspec->element_spec)
858     {
859       g_param_spec_unref (aspec->element_spec);
860       aspec->element_spec = NULL;
861     }
862
863   parent_class->finalize (pspec);
864 }
865
866 static void
867 param_value_array_set_default (GParamSpec *pspec,
868                                GValue     *value)
869 {
870   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
871
872   if (!value->data[0].v_pointer && aspec->fixed_n_elements)
873     value->data[0].v_pointer = g_value_array_new (aspec->fixed_n_elements);
874
875   if (value->data[0].v_pointer)
876     {
877       /* g_value_reset (value);  already done */
878       value_array_ensure_size (value->data[0].v_pointer, aspec->fixed_n_elements);
879     }
880 }
881
882 static gboolean
883 param_value_array_validate (GParamSpec *pspec,
884                             GValue     *value)
885 {
886   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
887   GValueArray *value_array = value->data[0].v_pointer;
888   guint changed = 0;
889
890   if (!value->data[0].v_pointer && aspec->fixed_n_elements)
891     value->data[0].v_pointer = g_value_array_new (aspec->fixed_n_elements);
892
893   if (value->data[0].v_pointer)
894     {
895       /* ensure array size validity */
896       changed += value_array_ensure_size (value_array, aspec->fixed_n_elements);
897       
898       /* ensure array values validity against a present element spec */
899       if (aspec->element_spec)
900         {
901           GParamSpec *element_spec = aspec->element_spec;
902           guint i;
903           
904           for (i = 0; i < value_array->n_values; i++)
905             {
906               GValue *element = value_array->values + i;
907               
908               /* need to fixup value type, or ensure that the array value is initialized at all */
909               if (!g_value_type_compatible (G_VALUE_TYPE (element), G_PARAM_SPEC_VALUE_TYPE (element_spec)))
910                 {
911                   if (G_VALUE_TYPE (element) != 0)
912                     g_value_unset (element);
913                   g_value_init (element, G_PARAM_SPEC_VALUE_TYPE (element_spec));
914                   g_param_value_set_default (element_spec, element);
915                   changed++;
916                 }
917               /* validate array value against element_spec */
918               changed += g_param_value_validate (element_spec, element);
919             }
920         }
921     }
922
923   return changed;
924 }
925
926 static gint
927 param_value_array_values_cmp (GParamSpec   *pspec,
928                               const GValue *value1,
929                               const GValue *value2)
930 {
931   GParamSpecValueArray *aspec = G_PARAM_SPEC_VALUE_ARRAY (pspec);
932   GValueArray *value_array1 = value1->data[0].v_pointer;
933   GValueArray *value_array2 = value2->data[0].v_pointer;
934
935   if (!value_array1 || !value_array2)
936     return value_array2 ? -1 : value_array1 != value_array2;
937
938   if (value_array1->n_values != value_array2->n_values)
939     return value_array1->n_values < value_array2->n_values ? -1 : 1;
940   else if (!aspec->element_spec)
941     {
942       /* we need an element specification for comparisons, so there's not much
943        * to compare here, try to at least provide stable lesser/greater result
944        */
945       return value_array1->n_values < value_array2->n_values ? -1 : value_array1->n_values > value_array2->n_values;
946     }
947   else /* value_array1->n_values == value_array2->n_values */
948     {
949       guint i;
950
951       for (i = 0; i < value_array1->n_values; i++)
952         {
953           GValue *element1 = value_array1->values + i;
954           GValue *element2 = value_array2->values + i;
955           gint cmp;
956
957           /* need corresponding element types, provide stable result otherwise */
958           if (G_VALUE_TYPE (element1) != G_VALUE_TYPE (element2))
959             return G_VALUE_TYPE (element1) < G_VALUE_TYPE (element2) ? -1 : 1;
960           cmp = g_param_values_cmp (aspec->element_spec, element1, element2);
961           if (cmp)
962             return cmp;
963         }
964       return 0;
965     }
966 }
967
968 static void
969 param_object_init (GParamSpec *pspec)
970 {
971   /* GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec); */
972 }
973
974 static void
975 param_object_set_default (GParamSpec *pspec,
976                           GValue     *value)
977 {
978   value->data[0].v_pointer = NULL;
979 }
980
981 static gboolean
982 param_object_validate (GParamSpec *pspec,
983                        GValue     *value)
984 {
985   GParamSpecObject *ospec = G_PARAM_SPEC_OBJECT (pspec);
986   GObject *object = value->data[0].v_pointer;
987   guint changed = 0;
988   
989   if (object && !g_value_type_compatible (G_OBJECT_TYPE (object), G_PARAM_SPEC_VALUE_TYPE (ospec)))
990     {
991       g_object_unref (object);
992       value->data[0].v_pointer = NULL;
993       changed++;
994     }
995   
996   return changed;
997 }
998
999 static gint
1000 param_object_values_cmp (GParamSpec   *pspec,
1001                          const GValue *value1,
1002                          const GValue *value2)
1003 {
1004   guint8 *p1 = value1->data[0].v_pointer;
1005   guint8 *p2 = value2->data[0].v_pointer;
1006
1007   /* not much to compare here, try to at least provide stable lesser/greater result */
1008
1009   return p1 < p2 ? -1 : p1 > p2;
1010 }
1011
1012 static void
1013 param_override_init (GParamSpec *pspec)
1014 {
1015   /* GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec); */
1016 }
1017
1018 static void
1019 param_override_finalize (GParamSpec *pspec)
1020 {
1021   GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
1022   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_OVERRIDE));
1023   
1024   if (ospec->overridden)
1025     {
1026       g_param_spec_unref (ospec->overridden);
1027       ospec->overridden = NULL;
1028     }
1029   
1030   parent_class->finalize (pspec);
1031 }
1032
1033 static void
1034 param_override_set_default (GParamSpec *pspec,
1035                             GValue     *value)
1036 {
1037   GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
1038
1039   g_param_value_set_default (ospec->overridden, value);
1040 }
1041
1042 static gboolean
1043 param_override_validate (GParamSpec *pspec,
1044                          GValue     *value)
1045 {
1046   GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
1047   
1048   return g_param_value_validate (ospec->overridden, value);
1049 }
1050
1051 static gint
1052 param_override_values_cmp (GParamSpec   *pspec,
1053                            const GValue *value1,
1054                            const GValue *value2)
1055 {
1056   GParamSpecOverride *ospec = G_PARAM_SPEC_OVERRIDE (pspec);
1057
1058   return g_param_values_cmp (ospec->overridden, value1, value2);
1059 }
1060
1061 static void
1062 param_gtype_init (GParamSpec *pspec)
1063 {
1064 }
1065
1066 static void
1067 param_gtype_set_default (GParamSpec *pspec,
1068                          GValue     *value)
1069 {
1070   GParamSpecGType *tspec = G_PARAM_SPEC_GTYPE (pspec);
1071
1072   value->data[0].v_long = tspec->is_a_type;
1073 }
1074
1075 static gboolean
1076 param_gtype_validate (GParamSpec *pspec,
1077                       GValue     *value)
1078 {
1079   GParamSpecGType *tspec = G_PARAM_SPEC_GTYPE (pspec);
1080   GType gtype = value->data[0].v_long;
1081   guint changed = 0;
1082   
1083   if (tspec->is_a_type != G_TYPE_NONE && !g_type_is_a (gtype, tspec->is_a_type))
1084     {
1085       value->data[0].v_long = tspec->is_a_type;
1086       changed++;
1087     }
1088   
1089   return changed;
1090 }
1091
1092 static gint
1093 param_gtype_values_cmp (GParamSpec   *pspec,
1094                         const GValue *value1,
1095                         const GValue *value2)
1096 {
1097   GType p1 = value1->data[0].v_long;
1098   GType p2 = value2->data[0].v_long;
1099
1100   /* not much to compare here, try to at least provide stable lesser/greater result */
1101
1102   return p1 < p2 ? -1 : p1 > p2;
1103 }
1104
1105 static void
1106 param_variant_init (GParamSpec *pspec)
1107 {
1108   GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (pspec);
1109
1110   vspec->type = NULL;
1111   vspec->default_value = NULL;
1112 }
1113
1114 static void
1115 param_variant_finalize (GParamSpec *pspec)
1116 {
1117   GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (pspec);
1118   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PARAM_VARIANT));
1119
1120   if (vspec->default_value)
1121     g_variant_unref (vspec->default_value);
1122   g_variant_type_free (vspec->type);
1123
1124   parent_class->finalize (pspec);
1125 }
1126
1127 static void
1128 param_variant_set_default (GParamSpec *pspec,
1129                            GValue     *value)
1130 {
1131   value->data[0].v_pointer = G_PARAM_SPEC_VARIANT (pspec)->default_value;
1132   value->data[1].v_uint |= G_VALUE_NOCOPY_CONTENTS;
1133 }
1134
1135 static gboolean
1136 param_variant_validate (GParamSpec *pspec,
1137                         GValue     *value)
1138 {
1139   GParamSpecVariant *vspec = G_PARAM_SPEC_VARIANT (pspec);
1140   GVariant *variant = value->data[0].v_pointer;
1141
1142   if ((variant == NULL && vspec->default_value != NULL) ||
1143       (variant != NULL && !g_variant_is_of_type (variant, vspec->type)))
1144     {
1145       g_param_value_set_default (pspec, value);
1146       return TRUE;
1147     }
1148
1149   return FALSE;
1150 }
1151
1152 static gint
1153 param_variant_values_cmp (GParamSpec   *pspec,
1154                           const GValue *value1,
1155                           const GValue *value2)
1156 {
1157   GVariant *v1 = value1->data[0].v_pointer;
1158   GVariant *v2 = value2->data[0].v_pointer;
1159
1160   return v1 < v2 ? -1 : v2 > v1;
1161 }
1162
1163 /* --- type initialization --- */
1164 GType *g_param_spec_types = NULL;
1165
1166 void
1167 _g_param_spec_types_init (void) 
1168 {
1169   const guint n_types = 23;
1170   GType type, *spec_types, *spec_types_bound;
1171
1172   g_param_spec_types = g_new0 (GType, n_types);
1173   spec_types = g_param_spec_types;
1174   spec_types_bound = g_param_spec_types + n_types;
1175   
1176   /* G_TYPE_PARAM_CHAR
1177    */
1178   {
1179     static const GParamSpecTypeInfo pspec_info = {
1180       sizeof (GParamSpecChar),  /* instance_size */
1181       16,                       /* n_preallocs */
1182       param_char_init,          /* instance_init */
1183       G_TYPE_CHAR,              /* value_type */
1184       NULL,                     /* finalize */
1185       param_char_set_default,   /* value_set_default */
1186       param_char_validate,      /* value_validate */
1187       param_int_values_cmp,     /* values_cmp */
1188     };
1189     type = g_param_type_register_static (g_intern_static_string ("GParamChar"), &pspec_info);
1190     *spec_types++ = type;
1191     g_assert (type == G_TYPE_PARAM_CHAR);
1192   }
1193   
1194   /* G_TYPE_PARAM_UCHAR
1195    */
1196   {
1197     static const GParamSpecTypeInfo pspec_info = {
1198       sizeof (GParamSpecUChar), /* instance_size */
1199       16,                       /* n_preallocs */
1200       param_uchar_init,         /* instance_init */
1201       G_TYPE_UCHAR,             /* value_type */
1202       NULL,                     /* finalize */
1203       param_uchar_set_default,  /* value_set_default */
1204       param_uchar_validate,     /* value_validate */
1205       param_uint_values_cmp,    /* values_cmp */
1206     };
1207     type = g_param_type_register_static (g_intern_static_string ("GParamUChar"), &pspec_info);
1208     *spec_types++ = type;
1209     g_assert (type == G_TYPE_PARAM_UCHAR);
1210   }
1211   
1212   /* G_TYPE_PARAM_BOOLEAN
1213    */
1214   {
1215     static const GParamSpecTypeInfo pspec_info = {
1216       sizeof (GParamSpecBoolean), /* instance_size */
1217       16,                         /* n_preallocs */
1218       NULL,                       /* instance_init */
1219       G_TYPE_BOOLEAN,             /* value_type */
1220       NULL,                       /* finalize */
1221       param_boolean_set_default,  /* value_set_default */
1222       param_boolean_validate,     /* value_validate */
1223       param_int_values_cmp,       /* values_cmp */
1224     };
1225     type = g_param_type_register_static (g_intern_static_string ("GParamBoolean"), &pspec_info);
1226     *spec_types++ = type;
1227     g_assert (type == G_TYPE_PARAM_BOOLEAN);
1228   }
1229   
1230   /* G_TYPE_PARAM_INT
1231    */
1232   {
1233     static const GParamSpecTypeInfo pspec_info = {
1234       sizeof (GParamSpecInt),   /* instance_size */
1235       16,                       /* n_preallocs */
1236       param_int_init,           /* instance_init */
1237       G_TYPE_INT,               /* value_type */
1238       NULL,                     /* finalize */
1239       param_int_set_default,    /* value_set_default */
1240       param_int_validate,       /* value_validate */
1241       param_int_values_cmp,     /* values_cmp */
1242     };
1243     type = g_param_type_register_static (g_intern_static_string ("GParamInt"), &pspec_info);
1244     *spec_types++ = type;
1245     g_assert (type == G_TYPE_PARAM_INT);
1246   }
1247   
1248   /* G_TYPE_PARAM_UINT
1249    */
1250   {
1251     static const GParamSpecTypeInfo pspec_info = {
1252       sizeof (GParamSpecUInt),  /* instance_size */
1253       16,                       /* n_preallocs */
1254       param_uint_init,          /* instance_init */
1255       G_TYPE_UINT,              /* value_type */
1256       NULL,                     /* finalize */
1257       param_uint_set_default,   /* value_set_default */
1258       param_uint_validate,      /* value_validate */
1259       param_uint_values_cmp,    /* values_cmp */
1260     };
1261     type = g_param_type_register_static (g_intern_static_string ("GParamUInt"), &pspec_info);
1262     *spec_types++ = type;
1263     g_assert (type == G_TYPE_PARAM_UINT);
1264   }
1265   
1266   /* G_TYPE_PARAM_LONG
1267    */
1268   {
1269     static const GParamSpecTypeInfo pspec_info = {
1270       sizeof (GParamSpecLong),  /* instance_size */
1271       16,                       /* n_preallocs */
1272       param_long_init,          /* instance_init */
1273       G_TYPE_LONG,              /* value_type */
1274       NULL,                     /* finalize */
1275       param_long_set_default,   /* value_set_default */
1276       param_long_validate,      /* value_validate */
1277       param_long_values_cmp,    /* values_cmp */
1278     };
1279     type = g_param_type_register_static (g_intern_static_string ("GParamLong"), &pspec_info);
1280     *spec_types++ = type;
1281     g_assert (type == G_TYPE_PARAM_LONG);
1282   }
1283   
1284   /* G_TYPE_PARAM_ULONG
1285    */
1286   {
1287     static const GParamSpecTypeInfo pspec_info = {
1288       sizeof (GParamSpecULong), /* instance_size */
1289       16,                       /* n_preallocs */
1290       param_ulong_init,         /* instance_init */
1291       G_TYPE_ULONG,             /* value_type */
1292       NULL,                     /* finalize */
1293       param_ulong_set_default,  /* value_set_default */
1294       param_ulong_validate,     /* value_validate */
1295       param_ulong_values_cmp,   /* values_cmp */
1296     };
1297     type = g_param_type_register_static (g_intern_static_string ("GParamULong"), &pspec_info);
1298     *spec_types++ = type;
1299     g_assert (type == G_TYPE_PARAM_ULONG);
1300   }
1301
1302   /* G_TYPE_PARAM_INT64
1303    */
1304   {
1305     static const GParamSpecTypeInfo pspec_info = {
1306       sizeof (GParamSpecInt64),  /* instance_size */
1307       16,                       /* n_preallocs */
1308       param_int64_init,         /* instance_init */
1309       G_TYPE_INT64,             /* value_type */
1310       NULL,                     /* finalize */
1311       param_int64_set_default,  /* value_set_default */
1312       param_int64_validate,     /* value_validate */
1313       param_int64_values_cmp,   /* values_cmp */
1314     };
1315     type = g_param_type_register_static (g_intern_static_string ("GParamInt64"), &pspec_info);
1316     *spec_types++ = type;
1317     g_assert (type == G_TYPE_PARAM_INT64);
1318   }
1319   
1320   /* G_TYPE_PARAM_UINT64
1321    */
1322   {
1323     static const GParamSpecTypeInfo pspec_info = {
1324       sizeof (GParamSpecUInt64), /* instance_size */
1325       16,                       /* n_preallocs */
1326       param_uint64_init,        /* instance_init */
1327       G_TYPE_UINT64,            /* value_type */
1328       NULL,                     /* finalize */
1329       param_uint64_set_default, /* value_set_default */
1330       param_uint64_validate,    /* value_validate */
1331       param_uint64_values_cmp,  /* values_cmp */
1332     };
1333     type = g_param_type_register_static (g_intern_static_string ("GParamUInt64"), &pspec_info);
1334     *spec_types++ = type;
1335     g_assert (type == G_TYPE_PARAM_UINT64);
1336   }
1337
1338   /* G_TYPE_PARAM_UNICHAR
1339    */
1340   {
1341     static const GParamSpecTypeInfo pspec_info = {
1342       sizeof (GParamSpecUnichar), /* instance_size */
1343       16,                        /* n_preallocs */
1344       param_unichar_init,        /* instance_init */
1345       G_TYPE_UINT,               /* value_type */
1346       NULL,                      /* finalize */
1347       param_unichar_set_default, /* value_set_default */
1348       param_unichar_validate,    /* value_validate */
1349       param_unichar_values_cmp,  /* values_cmp */
1350     };
1351     type = g_param_type_register_static (g_intern_static_string ("GParamUnichar"), &pspec_info);
1352     *spec_types++ = type;
1353     g_assert (type == G_TYPE_PARAM_UNICHAR);
1354   }
1355
1356  /* G_TYPE_PARAM_ENUM
1357    */
1358   {
1359     static const GParamSpecTypeInfo pspec_info = {
1360       sizeof (GParamSpecEnum),  /* instance_size */
1361       16,                       /* n_preallocs */
1362       param_enum_init,          /* instance_init */
1363       G_TYPE_ENUM,              /* value_type */
1364       param_enum_finalize,      /* finalize */
1365       param_enum_set_default,   /* value_set_default */
1366       param_enum_validate,      /* value_validate */
1367       param_long_values_cmp,    /* values_cmp */
1368     };
1369     type = g_param_type_register_static (g_intern_static_string ("GParamEnum"), &pspec_info);
1370     *spec_types++ = type;
1371     g_assert (type == G_TYPE_PARAM_ENUM);
1372   }
1373   
1374   /* G_TYPE_PARAM_FLAGS
1375    */
1376   {
1377     static const GParamSpecTypeInfo pspec_info = {
1378       sizeof (GParamSpecFlags), /* instance_size */
1379       16,                       /* n_preallocs */
1380       param_flags_init,         /* instance_init */
1381       G_TYPE_FLAGS,             /* value_type */
1382       param_flags_finalize,     /* finalize */
1383       param_flags_set_default,  /* value_set_default */
1384       param_flags_validate,     /* value_validate */
1385       param_ulong_values_cmp,   /* values_cmp */
1386     };
1387     type = g_param_type_register_static (g_intern_static_string ("GParamFlags"), &pspec_info);
1388     *spec_types++ = type;
1389     g_assert (type == G_TYPE_PARAM_FLAGS);
1390   }
1391   
1392   /* G_TYPE_PARAM_FLOAT
1393    */
1394   {
1395     static const GParamSpecTypeInfo pspec_info = {
1396       sizeof (GParamSpecFloat), /* instance_size */
1397       16,                       /* n_preallocs */
1398       param_float_init,         /* instance_init */
1399       G_TYPE_FLOAT,             /* value_type */
1400       NULL,                     /* finalize */
1401       param_float_set_default,  /* value_set_default */
1402       param_float_validate,     /* value_validate */
1403       param_float_values_cmp,   /* values_cmp */
1404     };
1405     type = g_param_type_register_static (g_intern_static_string ("GParamFloat"), &pspec_info);
1406     *spec_types++ = type;
1407     g_assert (type == G_TYPE_PARAM_FLOAT);
1408   }
1409   
1410   /* G_TYPE_PARAM_DOUBLE
1411    */
1412   {
1413     static const GParamSpecTypeInfo pspec_info = {
1414       sizeof (GParamSpecDouble),        /* instance_size */
1415       16,                               /* n_preallocs */
1416       param_double_init,                /* instance_init */
1417       G_TYPE_DOUBLE,                    /* value_type */
1418       NULL,                             /* finalize */
1419       param_double_set_default,         /* value_set_default */
1420       param_double_validate,            /* value_validate */
1421       param_double_values_cmp,          /* values_cmp */
1422     };
1423     type = g_param_type_register_static (g_intern_static_string ("GParamDouble"), &pspec_info);
1424     *spec_types++ = type;
1425     g_assert (type == G_TYPE_PARAM_DOUBLE);
1426   }
1427   
1428   /* G_TYPE_PARAM_STRING
1429    */
1430   {
1431     static const GParamSpecTypeInfo pspec_info = {
1432       sizeof (GParamSpecString),        /* instance_size */
1433       16,                               /* n_preallocs */
1434       param_string_init,                /* instance_init */
1435       G_TYPE_STRING,                    /* value_type */
1436       param_string_finalize,            /* finalize */
1437       param_string_set_default,         /* value_set_default */
1438       param_string_validate,            /* value_validate */
1439       param_string_values_cmp,          /* values_cmp */
1440     };
1441     type = g_param_type_register_static (g_intern_static_string ("GParamString"), &pspec_info);
1442     *spec_types++ = type;
1443     g_assert (type == G_TYPE_PARAM_STRING);
1444   }
1445   
1446   /* G_TYPE_PARAM_PARAM
1447    */
1448   {
1449     static const GParamSpecTypeInfo pspec_info = {
1450       sizeof (GParamSpecParam), /* instance_size */
1451       16,                       /* n_preallocs */
1452       param_param_init,         /* instance_init */
1453       G_TYPE_PARAM,             /* value_type */
1454       NULL,                     /* finalize */
1455       param_param_set_default,  /* value_set_default */
1456       param_param_validate,     /* value_validate */
1457       param_pointer_values_cmp, /* values_cmp */
1458     };
1459     type = g_param_type_register_static (g_intern_static_string ("GParamParam"), &pspec_info);
1460     *spec_types++ = type;
1461     g_assert (type == G_TYPE_PARAM_PARAM);
1462   }
1463   
1464   /* G_TYPE_PARAM_BOXED
1465    */
1466   {
1467     static const GParamSpecTypeInfo pspec_info = {
1468       sizeof (GParamSpecBoxed), /* instance_size */
1469       4,                        /* n_preallocs */
1470       param_boxed_init,         /* instance_init */
1471       G_TYPE_BOXED,             /* value_type */
1472       NULL,                     /* finalize */
1473       param_boxed_set_default,  /* value_set_default */
1474       param_boxed_validate,     /* value_validate */
1475       param_boxed_values_cmp,   /* values_cmp */
1476     };
1477     type = g_param_type_register_static (g_intern_static_string ("GParamBoxed"), &pspec_info);
1478     *spec_types++ = type;
1479     g_assert (type == G_TYPE_PARAM_BOXED);
1480   }
1481
1482   /* G_TYPE_PARAM_POINTER
1483    */
1484   {
1485     static const GParamSpecTypeInfo pspec_info = {
1486       sizeof (GParamSpecPointer),  /* instance_size */
1487       0,                           /* n_preallocs */
1488       param_pointer_init,          /* instance_init */
1489       G_TYPE_POINTER,              /* value_type */
1490       NULL,                        /* finalize */
1491       param_pointer_set_default,   /* value_set_default */
1492       param_pointer_validate,      /* value_validate */
1493       param_pointer_values_cmp,    /* values_cmp */
1494     };
1495     type = g_param_type_register_static (g_intern_static_string ("GParamPointer"), &pspec_info);
1496     *spec_types++ = type;
1497     g_assert (type == G_TYPE_PARAM_POINTER);
1498   }
1499   
1500   /* G_TYPE_PARAM_VALUE_ARRAY
1501    */
1502   {
1503     static /* const */ GParamSpecTypeInfo pspec_info = {
1504       sizeof (GParamSpecValueArray),    /* instance_size */
1505       0,                                /* n_preallocs */
1506       param_value_array_init,           /* instance_init */
1507       0xdeadbeef,                       /* value_type, assigned further down */
1508       param_value_array_finalize,       /* finalize */
1509       param_value_array_set_default,    /* value_set_default */
1510       param_value_array_validate,       /* value_validate */
1511       param_value_array_values_cmp,     /* values_cmp */
1512     };
1513     pspec_info.value_type = G_TYPE_VALUE_ARRAY;
1514     type = g_param_type_register_static (g_intern_static_string ("GParamValueArray"), &pspec_info);
1515     *spec_types++ = type;
1516     g_assert (type == G_TYPE_PARAM_VALUE_ARRAY);
1517   }
1518
1519   /* G_TYPE_PARAM_OBJECT
1520    */
1521   {
1522     static const GParamSpecTypeInfo pspec_info = {
1523       sizeof (GParamSpecObject), /* instance_size */
1524       16,                        /* n_preallocs */
1525       param_object_init,         /* instance_init */
1526       G_TYPE_OBJECT,             /* value_type */
1527       NULL,                      /* finalize */
1528       param_object_set_default,  /* value_set_default */
1529       param_object_validate,     /* value_validate */
1530       param_object_values_cmp,   /* values_cmp */
1531     };
1532     type = g_param_type_register_static (g_intern_static_string ("GParamObject"), &pspec_info);
1533     *spec_types++ = type;
1534     g_assert (type == G_TYPE_PARAM_OBJECT);
1535   }
1536
1537   /* G_TYPE_PARAM_OVERRIDE
1538    */
1539   {
1540     static const GParamSpecTypeInfo pspec_info = {
1541       sizeof (GParamSpecOverride), /* instance_size */
1542       16,                        /* n_preallocs */
1543       param_override_init,       /* instance_init */
1544       G_TYPE_NONE,               /* value_type */
1545       param_override_finalize,   /* finalize */
1546       param_override_set_default, /* value_set_default */
1547       param_override_validate,    /* value_validate */
1548       param_override_values_cmp,  /* values_cmp */
1549     };
1550     type = g_param_type_register_static (g_intern_static_string ("GParamOverride"), &pspec_info);
1551     *spec_types++ = type;
1552     g_assert (type == G_TYPE_PARAM_OVERRIDE);
1553   }
1554
1555   /* G_TYPE_PARAM_GTYPE
1556    */
1557   {
1558     GParamSpecTypeInfo pspec_info = {
1559       sizeof (GParamSpecGType), /* instance_size */
1560       0,                        /* n_preallocs */
1561       param_gtype_init,         /* instance_init */
1562       0xdeadbeef,               /* value_type, assigned further down */
1563       NULL,                     /* finalize */
1564       param_gtype_set_default,  /* value_set_default */
1565       param_gtype_validate,     /* value_validate */
1566       param_gtype_values_cmp,   /* values_cmp */
1567     };
1568     pspec_info.value_type = G_TYPE_GTYPE;
1569     type = g_param_type_register_static (g_intern_static_string ("GParamGType"), &pspec_info);
1570     *spec_types++ = type;
1571     g_assert (type == G_TYPE_PARAM_GTYPE);
1572   }
1573
1574   /* G_TYPE_PARAM_VARIANT
1575    */
1576   {
1577     const GParamSpecTypeInfo pspec_info = {
1578       sizeof (GParamSpecVariant), /* instance_size */
1579       0,                          /* n_preallocs */
1580       param_variant_init,         /* instance_init */
1581       G_TYPE_VARIANT,             /* value_type */
1582       param_variant_finalize,     /* finalize */
1583       param_variant_set_default,  /* value_set_default */
1584       param_variant_validate,     /* value_validate */
1585       param_variant_values_cmp,   /* values_cmp */
1586     };
1587     type = g_param_type_register_static (g_intern_static_string ("GParamVariant"), &pspec_info);
1588     *spec_types++ = type;
1589     g_assert (type == G_TYPE_PARAM_VARIANT);
1590   }
1591
1592   g_assert (spec_types == spec_types_bound);
1593 }
1594
1595 /* --- GParamSpec initialization --- */
1596
1597 /**
1598  * g_param_spec_char:
1599  * @name: canonical name of the property specified
1600  * @nick: nick name for the property specified
1601  * @blurb: description of the property specified
1602  * @minimum: minimum value for the property specified
1603  * @maximum: maximum value for the property specified
1604  * @default_value: default value for the property specified
1605  * @flags: flags for the property specified
1606  *
1607  * Creates a new #GParamSpecChar instance specifying a %G_TYPE_CHAR property.
1608  *
1609  * Returns: (transfer full): a newly created parameter specification
1610  */
1611 GParamSpec*
1612 g_param_spec_char (const gchar *name,
1613                    const gchar *nick,
1614                    const gchar *blurb,
1615                    gint8        minimum,
1616                    gint8        maximum,
1617                    gint8        default_value,
1618                    GParamFlags  flags)
1619 {
1620   GParamSpecChar *cspec;
1621
1622   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1623
1624   cspec = g_param_spec_internal (G_TYPE_PARAM_CHAR,
1625                                  name,
1626                                  nick,
1627                                  blurb,
1628                                  flags);
1629   if (cspec == NULL)
1630     return NULL;
1631   
1632   cspec->minimum = minimum;
1633   cspec->maximum = maximum;
1634   cspec->default_value = default_value;
1635   
1636   return G_PARAM_SPEC (cspec);
1637 }
1638
1639 /**
1640  * g_param_spec_uchar:
1641  * @name: canonical name of the property specified
1642  * @nick: nick name for the property specified
1643  * @blurb: description of the property specified
1644  * @minimum: minimum value for the property specified
1645  * @maximum: maximum value for the property specified
1646  * @default_value: default value for the property specified
1647  * @flags: flags for the property specified
1648  *
1649  * Creates a new #GParamSpecUChar instance specifying a %G_TYPE_UCHAR property.
1650  *
1651  * Returns: (transfer full): a newly created parameter specification
1652  */
1653 GParamSpec*
1654 g_param_spec_uchar (const gchar *name,
1655                     const gchar *nick,
1656                     const gchar *blurb,
1657                     guint8       minimum,
1658                     guint8       maximum,
1659                     guint8       default_value,
1660                     GParamFlags  flags)
1661 {
1662   GParamSpecUChar *uspec;
1663
1664   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1665
1666   uspec = g_param_spec_internal (G_TYPE_PARAM_UCHAR,
1667                                  name,
1668                                  nick,
1669                                  blurb,
1670                                  flags);
1671   if (uspec == NULL)
1672     return NULL;
1673   
1674   uspec->minimum = minimum;
1675   uspec->maximum = maximum;
1676   uspec->default_value = default_value;
1677   
1678   return G_PARAM_SPEC (uspec);
1679 }
1680
1681 /**
1682  * g_param_spec_boolean:
1683  * @name: canonical name of the property specified
1684  * @nick: nick name for the property specified
1685  * @blurb: description of the property specified
1686  * @default_value: default value for the property specified
1687  * @flags: flags for the property specified
1688  *
1689  * Creates a new #GParamSpecBoolean instance specifying a %G_TYPE_BOOLEAN
1690  * property.
1691  *
1692  * See g_param_spec_internal() for details on property names.
1693  *
1694  * Returns: (transfer full): a newly created parameter specification
1695  */
1696 GParamSpec*
1697 g_param_spec_boolean (const gchar *name,
1698                       const gchar *nick,
1699                       const gchar *blurb,
1700                       gboolean     default_value,
1701                       GParamFlags  flags)
1702 {
1703   GParamSpecBoolean *bspec;
1704
1705   g_return_val_if_fail (default_value == TRUE || default_value == FALSE, NULL);
1706
1707   bspec = g_param_spec_internal (G_TYPE_PARAM_BOOLEAN,
1708                                  name,
1709                                  nick,
1710                                  blurb,
1711                                  flags);
1712   if (bspec == NULL)
1713     return NULL;
1714   
1715   bspec->default_value = default_value;
1716   
1717   return G_PARAM_SPEC (bspec);
1718 }
1719
1720 /**
1721  * g_param_spec_int:
1722  * @name: canonical name of the property specified
1723  * @nick: nick name for the property specified
1724  * @blurb: description of the property specified
1725  * @minimum: minimum value for the property specified
1726  * @maximum: maximum value for the property specified
1727  * @default_value: default value for the property specified
1728  * @flags: flags for the property specified
1729  *
1730  * Creates a new #GParamSpecInt instance specifying a %G_TYPE_INT property.
1731  *
1732  * See g_param_spec_internal() for details on property names.
1733  *
1734  * Returns: (transfer full): a newly created parameter specification
1735  */
1736 GParamSpec*
1737 g_param_spec_int (const gchar *name,
1738                   const gchar *nick,
1739                   const gchar *blurb,
1740                   gint         minimum,
1741                   gint         maximum,
1742                   gint         default_value,
1743                   GParamFlags  flags)
1744 {
1745   GParamSpecInt *ispec;
1746
1747   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1748
1749   ispec = g_param_spec_internal (G_TYPE_PARAM_INT,
1750                                  name,
1751                                  nick,
1752                                  blurb,
1753                                  flags);
1754   if (ispec == NULL)
1755     return NULL;
1756   
1757   ispec->minimum = minimum;
1758   ispec->maximum = maximum;
1759   ispec->default_value = default_value;
1760   
1761   return G_PARAM_SPEC (ispec);
1762 }
1763
1764 /**
1765  * g_param_spec_uint:
1766  * @name: canonical name of the property specified
1767  * @nick: nick name for the property specified
1768  * @blurb: description of the property specified
1769  * @minimum: minimum value for the property specified
1770  * @maximum: maximum value for the property specified
1771  * @default_value: default value for the property specified
1772  * @flags: flags for the property specified
1773  *
1774  * Creates a new #GParamSpecUInt instance specifying a %G_TYPE_UINT property.
1775  *
1776  * See g_param_spec_internal() for details on property names.
1777  *
1778  * Returns: (transfer full): a newly created parameter specification
1779  */
1780 GParamSpec*
1781 g_param_spec_uint (const gchar *name,
1782                    const gchar *nick,
1783                    const gchar *blurb,
1784                    guint        minimum,
1785                    guint        maximum,
1786                    guint        default_value,
1787                    GParamFlags  flags)
1788 {
1789   GParamSpecUInt *uspec;
1790
1791   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1792
1793   uspec = g_param_spec_internal (G_TYPE_PARAM_UINT,
1794                                  name,
1795                                  nick,
1796                                  blurb,
1797                                  flags);
1798   if (uspec == NULL)
1799     return NULL;
1800   
1801   uspec->minimum = minimum;
1802   uspec->maximum = maximum;
1803   uspec->default_value = default_value;
1804   
1805   return G_PARAM_SPEC (uspec);
1806 }
1807
1808 /**
1809  * g_param_spec_long:
1810  * @name: canonical name of the property specified
1811  * @nick: nick name for the property specified
1812  * @blurb: description of the property specified
1813  * @minimum: minimum value for the property specified
1814  * @maximum: maximum value for the property specified
1815  * @default_value: default value for the property specified
1816  * @flags: flags for the property specified
1817  *
1818  * Creates a new #GParamSpecLong instance specifying a %G_TYPE_LONG property.
1819  *
1820  * See g_param_spec_internal() for details on property names.
1821  *
1822  * Returns: (transfer full): a newly created parameter specification
1823  */
1824 GParamSpec*
1825 g_param_spec_long (const gchar *name,
1826                    const gchar *nick,
1827                    const gchar *blurb,
1828                    glong        minimum,
1829                    glong        maximum,
1830                    glong        default_value,
1831                    GParamFlags  flags)
1832 {
1833   GParamSpecLong *lspec;
1834
1835   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1836
1837   lspec = g_param_spec_internal (G_TYPE_PARAM_LONG,
1838                                  name,
1839                                  nick,
1840                                  blurb,
1841                                  flags);
1842   if (lspec == NULL)
1843     return NULL;
1844   
1845   lspec->minimum = minimum;
1846   lspec->maximum = maximum;
1847   lspec->default_value = default_value;
1848   
1849   return G_PARAM_SPEC (lspec);
1850 }
1851
1852 /**
1853  * g_param_spec_ulong:
1854  * @name: canonical name of the property specified
1855  * @nick: nick name for the property specified
1856  * @blurb: description of the property specified
1857  * @minimum: minimum value for the property specified
1858  * @maximum: maximum value for the property specified
1859  * @default_value: default value for the property specified
1860  * @flags: flags for the property specified
1861  *
1862  * Creates a new #GParamSpecULong instance specifying a %G_TYPE_ULONG
1863  * property.
1864  *
1865  * See g_param_spec_internal() for details on property names.
1866  *
1867  * Returns: (transfer full): a newly created parameter specification
1868  */
1869 GParamSpec*
1870 g_param_spec_ulong (const gchar *name,
1871                     const gchar *nick,
1872                     const gchar *blurb,
1873                     gulong       minimum,
1874                     gulong       maximum,
1875                     gulong       default_value,
1876                     GParamFlags  flags)
1877 {
1878   GParamSpecULong *uspec;
1879
1880   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1881
1882   uspec = g_param_spec_internal (G_TYPE_PARAM_ULONG,
1883                                  name,
1884                                  nick,
1885                                  blurb,
1886                                  flags);
1887   if (uspec == NULL)
1888     return NULL;
1889   
1890   uspec->minimum = minimum;
1891   uspec->maximum = maximum;
1892   uspec->default_value = default_value;
1893   
1894   return G_PARAM_SPEC (uspec);
1895 }
1896
1897 /**
1898  * g_param_spec_int64:
1899  * @name: canonical name of the property specified
1900  * @nick: nick name for the property specified
1901  * @blurb: description of the property specified
1902  * @minimum: minimum value for the property specified
1903  * @maximum: maximum value for the property specified
1904  * @default_value: default value for the property specified
1905  * @flags: flags for the property specified
1906  *
1907  * Creates a new #GParamSpecInt64 instance specifying a %G_TYPE_INT64 property.
1908  *
1909  * See g_param_spec_internal() for details on property names.
1910  *
1911  * Returns: (transfer full): a newly created parameter specification
1912  */
1913 GParamSpec*
1914 g_param_spec_int64 (const gchar *name,
1915                     const gchar *nick,
1916                     const gchar *blurb,
1917                     gint64       minimum,
1918                     gint64       maximum,
1919                     gint64       default_value,
1920                     GParamFlags  flags)
1921 {
1922   GParamSpecInt64 *lspec;
1923   
1924   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1925
1926   lspec = g_param_spec_internal (G_TYPE_PARAM_INT64,
1927                                  name,
1928                                  nick,
1929                                  blurb,
1930                                  flags);
1931   if (lspec == NULL)
1932     return NULL;
1933   
1934   lspec->minimum = minimum;
1935   lspec->maximum = maximum;
1936   lspec->default_value = default_value;
1937   
1938   return G_PARAM_SPEC (lspec);
1939 }
1940
1941 /**
1942  * g_param_spec_uint64:
1943  * @name: canonical name of the property specified
1944  * @nick: nick name for the property specified
1945  * @blurb: description of the property specified
1946  * @minimum: minimum value for the property specified
1947  * @maximum: maximum value for the property specified
1948  * @default_value: default value for the property specified
1949  * @flags: flags for the property specified
1950  *
1951  * Creates a new #GParamSpecUInt64 instance specifying a %G_TYPE_UINT64
1952  * property.
1953  *
1954  * See g_param_spec_internal() for details on property names.
1955  *
1956  * Returns: (transfer full): a newly created parameter specification
1957  */
1958 GParamSpec*
1959 g_param_spec_uint64 (const gchar *name,
1960                      const gchar *nick,
1961                      const gchar *blurb,
1962                      guint64      minimum,
1963                      guint64      maximum,
1964                      guint64      default_value,
1965                      GParamFlags  flags)
1966 {
1967   GParamSpecUInt64 *uspec;
1968   
1969   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
1970   
1971   uspec = g_param_spec_internal (G_TYPE_PARAM_UINT64,
1972                                  name,
1973                                  nick,
1974                                  blurb,
1975                                  flags);
1976   if (uspec == NULL)
1977     return NULL;
1978   
1979   uspec->minimum = minimum;
1980   uspec->maximum = maximum;
1981   uspec->default_value = default_value;
1982   
1983   return G_PARAM_SPEC (uspec);
1984 }
1985
1986 /**
1987  * g_param_spec_unichar:
1988  * @name: canonical name of the property specified
1989  * @nick: nick name for the property specified
1990  * @blurb: description of the property specified
1991  * @default_value: default value for the property specified
1992  * @flags: flags for the property specified
1993  *
1994  * Creates a new #GParamSpecUnichar instance specifying a %G_TYPE_UINT
1995  * property. #GValue structures for this property can be accessed with
1996  * g_value_set_uint() and g_value_get_uint().
1997  *
1998  * See g_param_spec_internal() for details on property names.
1999  *
2000  * Returns: (transfer full): a newly created parameter specification
2001  */
2002 GParamSpec*
2003 g_param_spec_unichar (const gchar *name,
2004                       const gchar *nick,
2005                       const gchar *blurb,
2006                       gunichar     default_value,
2007                       GParamFlags  flags)
2008 {
2009   GParamSpecUnichar *uspec;
2010
2011   uspec = g_param_spec_internal (G_TYPE_PARAM_UNICHAR,
2012                                  name,
2013                                  nick,
2014                                  blurb,
2015                                  flags);
2016   if (uspec == NULL)
2017     return NULL;
2018   
2019   uspec->default_value = default_value;
2020   
2021   return G_PARAM_SPEC (uspec);
2022 }
2023
2024 /**
2025  * g_param_spec_enum:
2026  * @name: canonical name of the property specified
2027  * @nick: nick name for the property specified
2028  * @blurb: description of the property specified
2029  * @enum_type: a #GType derived from %G_TYPE_ENUM
2030  * @default_value: default value for the property specified
2031  * @flags: flags for the property specified
2032  *
2033  * Creates a new #GParamSpecEnum instance specifying a %G_TYPE_ENUM
2034  * property.
2035  *
2036  * See g_param_spec_internal() for details on property names.
2037  *
2038  * Returns: (transfer full): a newly created parameter specification
2039  */
2040 GParamSpec*
2041 g_param_spec_enum (const gchar *name,
2042                    const gchar *nick,
2043                    const gchar *blurb,
2044                    GType        enum_type,
2045                    gint         default_value,
2046                    GParamFlags  flags)
2047 {
2048   GParamSpecEnum *espec;
2049   GEnumClass *enum_class;
2050   
2051   g_return_val_if_fail (G_TYPE_IS_ENUM (enum_type), NULL);
2052
2053   enum_class = g_type_class_ref (enum_type);
2054
2055   g_return_val_if_fail (g_enum_get_value (enum_class, default_value) != NULL, NULL);
2056   
2057   espec = g_param_spec_internal (G_TYPE_PARAM_ENUM,
2058                                  name,
2059                                  nick,
2060                                  blurb,
2061                                  flags);
2062   if (espec == NULL)
2063     return NULL;
2064   
2065   espec->enum_class = enum_class;
2066   espec->default_value = default_value;
2067   G_PARAM_SPEC (espec)->value_type = enum_type;
2068   
2069   return G_PARAM_SPEC (espec);
2070 }
2071
2072 /**
2073  * g_param_spec_flags:
2074  * @name: canonical name of the property specified
2075  * @nick: nick name for the property specified
2076  * @blurb: description of the property specified
2077  * @flags_type: a #GType derived from %G_TYPE_FLAGS
2078  * @default_value: default value for the property specified
2079  * @flags: flags for the property specified
2080  *
2081  * Creates a new #GParamSpecFlags instance specifying a %G_TYPE_FLAGS
2082  * property.
2083  *
2084  * See g_param_spec_internal() for details on property names.
2085  *
2086  * Returns: (transfer full): a newly created parameter specification
2087  */
2088 GParamSpec*
2089 g_param_spec_flags (const gchar *name,
2090                     const gchar *nick,
2091                     const gchar *blurb,
2092                     GType        flags_type,
2093                     guint        default_value,
2094                     GParamFlags  flags)
2095 {
2096   GParamSpecFlags *fspec;
2097   GFlagsClass *flags_class;
2098   
2099   g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), NULL);
2100
2101   flags_class = g_type_class_ref (flags_type);
2102
2103   g_return_val_if_fail ((default_value & flags_class->mask) == default_value, NULL);
2104   
2105   fspec = g_param_spec_internal (G_TYPE_PARAM_FLAGS,
2106                                  name,
2107                                  nick,
2108                                  blurb,
2109                                  flags);
2110   if (fspec == NULL)
2111     return NULL;
2112   
2113   fspec->flags_class = flags_class;
2114   fspec->default_value = default_value;
2115   G_PARAM_SPEC (fspec)->value_type = flags_type;
2116   
2117   return G_PARAM_SPEC (fspec);
2118 }
2119
2120 /**
2121  * g_param_spec_float:
2122  * @name: canonical name of the property specified
2123  * @nick: nick name for the property specified
2124  * @blurb: description of the property specified
2125  * @minimum: minimum value for the property specified
2126  * @maximum: maximum value for the property specified
2127  * @default_value: default value for the property specified
2128  * @flags: flags for the property specified
2129  *
2130  * Creates a new #GParamSpecFloat instance specifying a %G_TYPE_FLOAT property.
2131  *
2132  * See g_param_spec_internal() for details on property names.
2133  *
2134  * Returns: (transfer full): a newly created parameter specification
2135  */
2136 GParamSpec*
2137 g_param_spec_float (const gchar *name,
2138                     const gchar *nick,
2139                     const gchar *blurb,
2140                     gfloat       minimum,
2141                     gfloat       maximum,
2142                     gfloat       default_value,
2143                     GParamFlags  flags)
2144 {
2145   GParamSpecFloat *fspec;
2146
2147   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
2148
2149   fspec = g_param_spec_internal (G_TYPE_PARAM_FLOAT,
2150                                  name,
2151                                  nick,
2152                                  blurb,
2153                                  flags);
2154   if (fspec == NULL)
2155     return NULL;
2156   
2157   fspec->minimum = minimum;
2158   fspec->maximum = maximum;
2159   fspec->default_value = default_value;
2160   
2161   return G_PARAM_SPEC (fspec);
2162 }
2163
2164 /**
2165  * g_param_spec_double:
2166  * @name: canonical name of the property specified
2167  * @nick: nick name for the property specified
2168  * @blurb: description of the property specified
2169  * @minimum: minimum value for the property specified
2170  * @maximum: maximum value for the property specified
2171  * @default_value: default value for the property specified
2172  * @flags: flags for the property specified
2173  *
2174  * Creates a new #GParamSpecDouble instance specifying a %G_TYPE_DOUBLE
2175  * property.
2176  *
2177  * See g_param_spec_internal() for details on property names.
2178  *
2179  * Returns: (transfer full): a newly created parameter specification
2180  */
2181 GParamSpec*
2182 g_param_spec_double (const gchar *name,
2183                      const gchar *nick,
2184                      const gchar *blurb,
2185                      gdouble      minimum,
2186                      gdouble      maximum,
2187                      gdouble      default_value,
2188                      GParamFlags  flags)
2189 {
2190   GParamSpecDouble *dspec;
2191
2192   g_return_val_if_fail (default_value >= minimum && default_value <= maximum, NULL);
2193
2194   dspec = g_param_spec_internal (G_TYPE_PARAM_DOUBLE,
2195                                  name,
2196                                  nick,
2197                                  blurb,
2198                                  flags);
2199   if (dspec == NULL)
2200     return NULL;
2201   
2202   dspec->minimum = minimum;
2203   dspec->maximum = maximum;
2204   dspec->default_value = default_value;
2205   
2206   return G_PARAM_SPEC (dspec);
2207 }
2208
2209 /**
2210  * g_param_spec_string:
2211  * @name: canonical name of the property specified
2212  * @nick: nick name for the property specified
2213  * @blurb: description of the property specified
2214  * @default_value: default value for the property specified
2215  * @flags: flags for the property specified
2216  *
2217  * Creates a new #GParamSpecString instance.
2218  *
2219  * See g_param_spec_internal() for details on property names.
2220  *
2221  * Returns: (transfer full): a newly created parameter specification
2222  */
2223 GParamSpec*
2224 g_param_spec_string (const gchar *name,
2225                      const gchar *nick,
2226                      const gchar *blurb,
2227                      const gchar *default_value,
2228                      GParamFlags  flags)
2229 {
2230   GParamSpecString *sspec = g_param_spec_internal (G_TYPE_PARAM_STRING,
2231                                                    name,
2232                                                    nick,
2233                                                    blurb,
2234                                                    flags);
2235   if (sspec == NULL)
2236     return NULL;
2237
2238   g_free (sspec->default_value);
2239   sspec->default_value = g_strdup (default_value);
2240   
2241   return G_PARAM_SPEC (sspec);
2242 }
2243
2244 /**
2245  * g_param_spec_param:
2246  * @name: canonical name of the property specified
2247  * @nick: nick name for the property specified
2248  * @blurb: description of the property specified
2249  * @param_type: a #GType derived from %G_TYPE_PARAM
2250  * @flags: flags for the property specified
2251  *
2252  * Creates a new #GParamSpecParam instance specifying a %G_TYPE_PARAM
2253  * property.
2254  *
2255  * See g_param_spec_internal() for details on property names.
2256  *
2257  * Returns: (transfer full): a newly created parameter specification
2258  */
2259 GParamSpec*
2260 g_param_spec_param (const gchar *name,
2261                     const gchar *nick,
2262                     const gchar *blurb,
2263                     GType        param_type,
2264                     GParamFlags  flags)
2265 {
2266   GParamSpecParam *pspec;
2267   
2268   g_return_val_if_fail (G_TYPE_IS_PARAM (param_type), NULL);
2269   
2270   pspec = g_param_spec_internal (G_TYPE_PARAM_PARAM,
2271                                  name,
2272                                  nick,
2273                                  blurb,
2274                                  flags);
2275   if (pspec == NULL)
2276     return NULL;
2277
2278   G_PARAM_SPEC (pspec)->value_type = param_type;
2279   
2280   return G_PARAM_SPEC (pspec);
2281 }
2282
2283 /**
2284  * g_param_spec_boxed:
2285  * @name: canonical name of the property specified
2286  * @nick: nick name for the property specified
2287  * @blurb: description of the property specified
2288  * @boxed_type: %G_TYPE_BOXED derived type of this property
2289  * @flags: flags for the property specified
2290  *
2291  * Creates a new #GParamSpecBoxed instance specifying a %G_TYPE_BOXED
2292  * derived property.
2293  *
2294  * See g_param_spec_internal() for details on property names.
2295  *
2296  * Returns: (transfer full): a newly created parameter specification
2297  */
2298 GParamSpec*
2299 g_param_spec_boxed (const gchar *name,
2300                     const gchar *nick,
2301                     const gchar *blurb,
2302                     GType        boxed_type,
2303                     GParamFlags  flags)
2304 {
2305   GParamSpecBoxed *bspec;
2306   
2307   g_return_val_if_fail (G_TYPE_IS_BOXED (boxed_type), NULL);
2308   g_return_val_if_fail (G_TYPE_IS_VALUE_TYPE (boxed_type), NULL);
2309   
2310   bspec = g_param_spec_internal (G_TYPE_PARAM_BOXED,
2311                                  name,
2312                                  nick,
2313                                  blurb,
2314                                  flags);
2315   if (bspec == NULL)
2316     return NULL;
2317
2318   G_PARAM_SPEC (bspec)->value_type = boxed_type;
2319   
2320   return G_PARAM_SPEC (bspec);
2321 }
2322
2323 /**
2324  * g_param_spec_pointer:
2325  * @name: canonical name of the property specified
2326  * @nick: nick name for the property specified
2327  * @blurb: description of the property specified
2328  * @flags: flags for the property specified
2329  *
2330  * Creates a new #GParamSpecPointer instance specifying a pointer property.
2331  *
2332  * See g_param_spec_internal() for details on property names.
2333  *
2334  * Returns: (transfer full): a newly created parameter specification
2335  */
2336 GParamSpec*
2337 g_param_spec_pointer (const gchar *name,
2338                       const gchar *nick,
2339                       const gchar *blurb,
2340                       GParamFlags  flags)
2341 {
2342   GParamSpecPointer *pspec;
2343   
2344   pspec = g_param_spec_internal (G_TYPE_PARAM_POINTER,
2345                                  name,
2346                                  nick,
2347                                  blurb,
2348                                  flags);
2349   if (pspec == NULL)
2350     return NULL;
2351
2352   return G_PARAM_SPEC (pspec);
2353 }
2354
2355 /**
2356  * g_param_spec_gtype:
2357  * @name: canonical name of the property specified
2358  * @nick: nick name for the property specified
2359  * @blurb: description of the property specified
2360  * @is_a_type: a #GType whose subtypes are allowed as values
2361  *  of the property (use %G_TYPE_NONE for any type)
2362  * @flags: flags for the property specified
2363  *
2364  * Creates a new #GParamSpecGType instance specifying a
2365  * %G_TYPE_GTYPE property.
2366  *
2367  * See g_param_spec_internal() for details on property names.
2368  *
2369  * Since: 2.10
2370  *
2371  * Returns: (transfer full): a newly created parameter specification
2372  */
2373 GParamSpec*
2374 g_param_spec_gtype (const gchar *name,
2375                     const gchar *nick,
2376                     const gchar *blurb,
2377                     GType        is_a_type,
2378                     GParamFlags  flags)
2379 {
2380   GParamSpecGType *tspec;
2381   
2382   tspec = g_param_spec_internal (G_TYPE_PARAM_GTYPE,
2383                                  name,
2384                                  nick,
2385                                  blurb,
2386                                  flags);
2387   if (tspec == NULL)
2388     return NULL;
2389
2390   tspec->is_a_type = is_a_type;
2391
2392   return G_PARAM_SPEC (tspec);
2393 }
2394
2395 /**
2396  * g_param_spec_value_array: (skip)
2397  * @name: canonical name of the property specified
2398  * @nick: nick name for the property specified
2399  * @blurb: description of the property specified
2400  * @element_spec: a #GParamSpec describing the elements contained in
2401  *  arrays of this property, may be %NULL
2402  * @flags: flags for the property specified
2403  *
2404  * Creates a new #GParamSpecValueArray instance specifying a
2405  * %G_TYPE_VALUE_ARRAY property. %G_TYPE_VALUE_ARRAY is a
2406  * %G_TYPE_BOXED type, as such, #GValue structures for this property
2407  * can be accessed with g_value_set_boxed() and g_value_get_boxed().
2408  *
2409  * See g_param_spec_internal() for details on property names.
2410  *
2411  * Returns: a newly created parameter specification
2412  */
2413 GParamSpec*
2414 g_param_spec_value_array (const gchar *name,
2415                           const gchar *nick,
2416                           const gchar *blurb,
2417                           GParamSpec  *element_spec,
2418                           GParamFlags  flags)
2419 {
2420   GParamSpecValueArray *aspec;
2421   
2422   if (element_spec)
2423     g_return_val_if_fail (G_IS_PARAM_SPEC (element_spec), NULL);
2424   
2425   aspec = g_param_spec_internal (G_TYPE_PARAM_VALUE_ARRAY,
2426                                  name,
2427                                  nick,
2428                                  blurb,
2429                                  flags);
2430   if (aspec == NULL)
2431     return NULL;
2432
2433   if (element_spec)
2434     {
2435       aspec->element_spec = g_param_spec_ref (element_spec);
2436       g_param_spec_sink (element_spec);
2437     }
2438
2439   return G_PARAM_SPEC (aspec);
2440 }
2441
2442 /**
2443  * g_param_spec_object:
2444  * @name: canonical name of the property specified
2445  * @nick: nick name for the property specified
2446  * @blurb: description of the property specified
2447  * @object_type: %G_TYPE_OBJECT derived type of this property
2448  * @flags: flags for the property specified
2449  *
2450  * Creates a new #GParamSpecBoxed instance specifying a %G_TYPE_OBJECT
2451  * derived property.
2452  *
2453  * See g_param_spec_internal() for details on property names.
2454  *
2455  * Returns: (transfer full): a newly created parameter specification
2456  */
2457 GParamSpec*
2458 g_param_spec_object (const gchar *name,
2459                      const gchar *nick,
2460                      const gchar *blurb,
2461                      GType        object_type,
2462                      GParamFlags  flags)
2463 {
2464   GParamSpecObject *ospec;
2465   
2466   g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT), NULL);
2467   
2468   ospec = g_param_spec_internal (G_TYPE_PARAM_OBJECT,
2469                                  name,
2470                                  nick,
2471                                  blurb,
2472                                  flags);
2473   if (ospec == NULL)
2474     return NULL;
2475
2476   G_PARAM_SPEC (ospec)->value_type = object_type;
2477   
2478   return G_PARAM_SPEC (ospec);
2479 }
2480
2481 /**
2482  * g_param_spec_override: (skip)
2483  * @name: the name of the property.
2484  * @overridden: The property that is being overridden
2485  *
2486  * Creates a new property of type #GParamSpecOverride. This is used
2487  * to direct operations to another paramspec, and will not be directly
2488  * useful unless you are implementing a new base type similar to GObject.
2489  *
2490  * Since: 2.4
2491  *
2492  * Returns: the newly created #GParamSpec
2493  */
2494 GParamSpec*
2495 g_param_spec_override (const gchar *name,
2496                        GParamSpec  *overridden)
2497 {
2498   GParamSpec *pspec;
2499   
2500   g_return_val_if_fail (name != NULL, NULL);
2501   g_return_val_if_fail (G_IS_PARAM_SPEC (overridden), NULL);
2502   
2503   /* Dereference further redirections for property that was passed in
2504    */
2505   while (TRUE)
2506     {
2507       GParamSpec *indirect = g_param_spec_get_redirect_target (overridden);
2508       if (indirect)
2509         overridden = indirect;
2510       else
2511         break;
2512     }
2513
2514   pspec = g_param_spec_internal (G_TYPE_PARAM_OVERRIDE,
2515                                  name, NULL, NULL,
2516                                  overridden->flags);
2517   if (pspec == NULL)
2518     return NULL;
2519   
2520   pspec->value_type = G_PARAM_SPEC_VALUE_TYPE (overridden);
2521   G_PARAM_SPEC_OVERRIDE (pspec)->overridden = g_param_spec_ref (overridden);
2522
2523   return pspec;
2524 }
2525
2526 /**
2527  * g_param_spec_variant:
2528  * @name: canonical name of the property specified
2529  * @nick: nick name for the property specified
2530  * @blurb: description of the property specified
2531  * @type: a #GVariantType
2532  * @default_value: (allow-none) (transfer full): a #GVariant of type @type to
2533  *                 use as the default value, or %NULL
2534  * @flags: flags for the property specified
2535  *
2536  * Creates a new #GParamSpecVariant instance specifying a #GVariant
2537  * property.
2538  *
2539  * If @default_value is floating, it is consumed.
2540  *
2541  * See g_param_spec_internal() for details on property names.
2542  *
2543  * Returns: (transfer full): the newly created #GParamSpec
2544  *
2545  * Since: 2.26
2546  */
2547 GParamSpec*
2548 g_param_spec_variant (const gchar        *name,
2549                       const gchar        *nick,
2550                       const gchar        *blurb,
2551                       const GVariantType *type,
2552                       GVariant           *default_value,
2553                       GParamFlags         flags)
2554 {
2555   GParamSpecVariant *vspec;
2556
2557   g_return_val_if_fail (type != NULL, NULL);
2558   g_return_val_if_fail (default_value == NULL ||
2559                         g_variant_is_of_type (default_value, type), NULL);
2560
2561   vspec = g_param_spec_internal (G_TYPE_PARAM_VARIANT,
2562                                  name,
2563                                  nick,
2564                                  blurb,
2565                                  flags);
2566   if (vspec == NULL)
2567     return NULL;
2568
2569   vspec->type = g_variant_type_copy (type);
2570   if (default_value)
2571     vspec->default_value = g_variant_ref_sink (default_value);
2572
2573   return G_PARAM_SPEC (vspec);
2574 }