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