changed prototype of g_boxed_type_register_static() to contain an optional
[platform/upstream/glib.git] / gobject / gvaluetypes.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        "gvaluetypes.h"
25
26 #include        "gvaluecollector.h"
27 #include        <string.h>
28 #include        <stdlib.h>      /* qsort() */
29
30
31 /* --- value functions --- */
32 static void
33 value_init_long0 (GValue *value)
34 {
35   value->data[0].v_long = 0;
36 }
37
38 static void
39 value_copy_long0 (const GValue *src_value,
40                   GValue       *dest_value)
41 {
42   dest_value->data[0].v_long = src_value->data[0].v_long;
43 }
44
45 static gchar*
46 value_lcopy_char (const GValue *value,
47                   guint         n_collect_values,
48                   GTypeCValue  *collect_values,
49                   guint         collect_flags)
50 {
51   gint8 *int8_p = collect_values[0].v_pointer;
52   
53   if (!int8_p)
54     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
55   
56   *int8_p = value->data[0].v_int;
57   
58   return NULL;
59 }
60
61 static gchar*
62 value_lcopy_boolean (const GValue *value,
63                      guint         n_collect_values,
64                      GTypeCValue  *collect_values,
65                      guint         collect_flags)
66 {
67   gboolean *bool_p = collect_values[0].v_pointer;
68   
69   if (!bool_p)
70     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
71   
72   *bool_p = value->data[0].v_int;
73   
74   return NULL;
75 }
76
77 static gchar*
78 value_collect_int (GValue      *value,
79                    guint        n_collect_values,
80                    GTypeCValue *collect_values,
81                    guint        collect_flags)
82 {
83   value->data[0].v_int = collect_values[0].v_int;
84   
85   return NULL;
86 }
87
88 static gchar*
89 value_lcopy_int (const GValue *value,
90                  guint         n_collect_values,
91                  GTypeCValue  *collect_values,
92                  guint         collect_flags)
93 {
94   gint *int_p = collect_values[0].v_pointer;
95   
96   if (!int_p)
97     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
98   
99   *int_p = value->data[0].v_int;
100   
101   return NULL;
102 }
103
104 static gchar*
105 value_collect_long (GValue      *value,
106                     guint        n_collect_values,
107                     GTypeCValue *collect_values,
108                     guint        collect_flags)
109 {
110   value->data[0].v_long = collect_values[0].v_long;
111   
112   return NULL;
113 }
114
115 static gchar*
116 value_lcopy_long (const GValue *value,
117                   guint         n_collect_values,
118                   GTypeCValue  *collect_values,
119                   guint         collect_flags)
120 {
121   glong *long_p = collect_values[0].v_pointer;
122   
123   if (!long_p)
124     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
125   
126   *long_p = value->data[0].v_long;
127   
128   return NULL;
129 }
130
131 static void
132 value_init_float (GValue *value)
133 {
134   value->data[0].v_float = 0.0;
135 }
136
137 static void
138 value_copy_float (const GValue *src_value,
139                   GValue       *dest_value)
140 {
141   dest_value->data[0].v_float = src_value->data[0].v_float;
142 }
143
144 static gchar*
145 value_collect_float (GValue      *value,
146                      guint        n_collect_values,
147                      GTypeCValue *collect_values,
148                      guint        collect_flags)
149 {
150   value->data[0].v_float = collect_values[0].v_double;
151   
152   return NULL;
153 }
154
155 static gchar*
156 value_lcopy_float (const GValue *value,
157                    guint         n_collect_values,
158                    GTypeCValue  *collect_values,
159                    guint         collect_flags)
160 {
161   gfloat *float_p = collect_values[0].v_pointer;
162   
163   if (!float_p)
164     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
165   
166   *float_p = value->data[0].v_float;
167   
168   return NULL;
169 }
170
171 static void
172 value_init_double (GValue *value)
173 {
174   value->data[0].v_double = 0.0;
175 }
176
177 static void
178 value_copy_double (const GValue *src_value,
179                    GValue       *dest_value)
180 {
181   dest_value->data[0].v_double = src_value->data[0].v_double;
182 }
183
184 static gchar*
185 value_collect_double (GValue      *value,
186                       guint        n_collect_values,
187                       GTypeCValue *collect_values,
188                       guint        collect_flags)
189 {
190   value->data[0].v_double = collect_values[0].v_double;
191   
192   return NULL;
193 }
194
195 static gchar*
196 value_lcopy_double (const GValue *value,
197                     guint         n_collect_values,
198                     GTypeCValue  *collect_values,
199                     guint         collect_flags)
200 {
201   gdouble *double_p = collect_values[0].v_pointer;
202   
203   if (!double_p)
204     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
205   
206   *double_p = value->data[0].v_double;
207   
208   return NULL;
209 }
210
211 static void
212 value_init_string (GValue *value)
213 {
214   value->data[0].v_pointer = NULL;
215 }
216
217 static void
218 value_free_string (GValue *value)
219 {
220   if (!(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
221     g_free (value->data[0].v_pointer);
222 }
223
224 static void
225 value_copy_string (const GValue *src_value,
226                    GValue       *dest_value)
227 {
228   dest_value->data[0].v_pointer = g_strdup (src_value->data[0].v_pointer);
229 }
230
231 static gchar*
232 value_collect_string (GValue      *value,
233                       guint        n_collect_values,
234                       GTypeCValue *collect_values,
235                       guint        collect_flags)
236 {
237   if (!collect_values[0].v_pointer)
238     value->data[0].v_pointer = NULL;
239   else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
240     {
241       value->data[0].v_pointer = collect_values[0].v_pointer;
242       value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
243     }
244   else
245     value->data[0].v_pointer = g_strdup (collect_values[0].v_pointer);
246   
247   return NULL;
248 }
249
250 static gchar*
251 value_lcopy_string (const GValue *value,
252                     guint         n_collect_values,
253                     GTypeCValue  *collect_values,
254                     guint         collect_flags)
255 {
256   gchar **string_p = collect_values[0].v_pointer;
257   
258   if (!string_p)
259     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
260   
261   if (!value->data[0].v_pointer)
262     *string_p = NULL;
263   else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
264     *string_p = value->data[0].v_pointer;
265   else
266     *string_p = g_strdup (value->data[0].v_pointer);
267   
268   return NULL;
269 }
270
271 static void
272 value_init_pointer (GValue *value)
273 {
274   value->data[0].v_pointer = NULL;
275 }
276
277 static void
278 value_copy_pointer (const GValue *src_value,
279                     GValue       *dest_value)
280 {
281   dest_value->data[0].v_pointer = src_value->data[0].v_pointer;
282 }
283
284 static gpointer
285 value_peek_pointer0 (const GValue *value)
286 {
287   return value->data[0].v_pointer;
288 }
289
290 static gchar*
291 value_collect_pointer (GValue      *value,
292                        guint        n_collect_values,
293                        GTypeCValue *collect_values,
294                        guint        collect_flags)
295 {
296   value->data[0].v_pointer = collect_values[0].v_pointer;
297
298   return NULL;
299 }
300
301 static gchar*
302 value_lcopy_pointer (const GValue *value,
303                      guint         n_collect_values,
304                      GTypeCValue  *collect_values,
305                      guint         collect_flags)
306 {
307   gpointer *pointer_p = collect_values[0].v_pointer;
308
309   if (!pointer_p)
310     return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
311
312   *pointer_p = value->data[0].v_pointer;
313
314   return NULL;
315 }
316
317
318 /* --- type initialization --- */
319 void
320 g_value_types_init (void)  /* sync with gtype.c */
321 {
322   GTypeInfo info = {
323     0,                          /* class_size */
324     NULL,                       /* base_init */
325     NULL,                       /* base_destroy */
326     NULL,                       /* class_init */
327     NULL,                       /* class_destroy */
328     NULL,                       /* class_data */
329     0,                          /* instance_size */
330     0,                          /* n_preallocs */
331     NULL,                       /* instance_init */
332     NULL,                       /* value_table */
333   };
334   const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_DERIVABLE, };
335   GType type;
336   
337   /* G_TYPE_CHAR / G_TYPE_UCHAR
338    */
339   {
340     static const GTypeValueTable value_table = {
341       value_init_long0,         /* value_init */
342       NULL,                     /* value_free */
343       value_copy_long0,         /* value_copy */
344       NULL,                     /* value_peek_pointer */
345       "i",                      /* collect_format */
346       value_collect_int,        /* collect_value */
347       "p",                      /* lcopy_format */
348       value_lcopy_char,         /* lcopy_value */
349     };
350     info.value_table = &value_table;
351     type = g_type_register_fundamental (G_TYPE_CHAR, "gchar", &info, &finfo, 0);
352     g_assert (type == G_TYPE_CHAR);
353     type = g_type_register_fundamental (G_TYPE_UCHAR, "guchar", &info, &finfo, 0);
354     g_assert (type == G_TYPE_UCHAR);
355   }
356
357   /* G_TYPE_BOOLEAN
358    */
359   {
360     static const GTypeValueTable value_table = {
361       value_init_long0,          /* value_init */
362       NULL,                      /* value_free */
363       value_copy_long0,          /* value_copy */
364       NULL,                      /* value_peek_pointer */
365       "i",                       /* collect_format */
366       value_collect_int,         /* collect_value */
367       "p",                       /* lcopy_format */
368       value_lcopy_boolean,       /* lcopy_value */
369     };
370     info.value_table = &value_table;
371     type = g_type_register_fundamental (G_TYPE_BOOLEAN, "gboolean", &info, &finfo, 0);
372     g_assert (type == G_TYPE_BOOLEAN);
373   }
374   
375   /* G_TYPE_INT / G_TYPE_UINT
376    */
377   {
378     static const GTypeValueTable value_table = {
379       value_init_long0,         /* value_init */
380       NULL,                     /* value_free */
381       value_copy_long0,         /* value_copy */
382       NULL,                     /* value_peek_pointer */
383       "i",                      /* collect_format */
384       value_collect_int,        /* collect_value */
385       "p",                      /* lcopy_format */
386       value_lcopy_int,          /* lcopy_value */
387     };
388     info.value_table = &value_table;
389     type = g_type_register_fundamental (G_TYPE_INT, "gint", &info, &finfo, 0);
390     g_assert (type == G_TYPE_INT);
391     type = g_type_register_fundamental (G_TYPE_UINT, "guint", &info, &finfo, 0);
392     g_assert (type == G_TYPE_UINT);
393   }
394
395   /* G_TYPE_LONG / G_TYPE_ULONG
396    */
397   {
398     static const GTypeValueTable value_table = {
399       value_init_long0,         /* value_init */
400       NULL,                     /* value_free */
401       value_copy_long0,         /* value_copy */
402       NULL,                     /* value_peek_pointer */
403       "l",                      /* collect_format */
404       value_collect_long,       /* collect_value */
405       "p",                      /* lcopy_format */
406       value_lcopy_long,         /* lcopy_value */
407     };
408     info.value_table = &value_table;
409     type = g_type_register_fundamental (G_TYPE_LONG, "glong", &info, &finfo, 0);
410     g_assert (type == G_TYPE_LONG);
411     type = g_type_register_fundamental (G_TYPE_ULONG, "gulong", &info, &finfo, 0);
412     g_assert (type == G_TYPE_ULONG);
413   }
414   
415   /* G_TYPE_FLOAT
416    */
417   {
418     static const GTypeValueTable value_table = {
419       value_init_float,          /* value_init */
420       NULL,                      /* value_free */
421       value_copy_float,          /* value_copy */
422       NULL,                      /* value_peek_pointer */
423       "d",                       /* collect_format */
424       value_collect_float,       /* collect_value */
425       "p",                       /* lcopy_format */
426       value_lcopy_float,         /* lcopy_value */
427     };
428     info.value_table = &value_table;
429     type = g_type_register_fundamental (G_TYPE_FLOAT, "gfloat", &info, &finfo, 0);
430     g_assert (type == G_TYPE_FLOAT);
431   }
432   
433   /* G_TYPE_DOUBLE
434    */
435   {
436     static const GTypeValueTable value_table = {
437       value_init_double,        /* value_init */
438       NULL,                     /* value_free */
439       value_copy_double,        /* value_copy */
440       NULL,                     /* value_peek_pointer */
441       "d",                      /* collect_format */
442       value_collect_double,     /* collect_value */
443       "p",                      /* lcopy_format */
444       value_lcopy_double,       /* lcopy_value */
445     };
446     info.value_table = &value_table;
447     type = g_type_register_fundamental (G_TYPE_DOUBLE, "gdouble", &info, &finfo, 0);
448     g_assert (type == G_TYPE_DOUBLE);
449   }
450
451   /* G_TYPE_STRING
452    */
453   {
454     static const GTypeValueTable value_table = {
455       value_init_string,        /* value_init */
456       value_free_string,        /* value_free */
457       value_copy_string,        /* value_copy */
458       value_peek_pointer0,      /* value_peek_pointer */
459       "p",                      /* collect_format */
460       value_collect_string,     /* collect_value */
461       "p",                      /* lcopy_format */
462       value_lcopy_string,       /* lcopy_value */
463     };
464     info.value_table = &value_table;
465     type = g_type_register_fundamental (G_TYPE_STRING, "gstring", &info, &finfo, 0);
466     g_assert (type == G_TYPE_STRING);
467   }
468
469   /* G_TYPE_POINTER
470    */
471   {
472     static const GTypeValueTable value_table = {
473       value_init_pointer,       /* value_init */
474       NULL,                     /* value_free */
475       value_copy_pointer,       /* value_copy */
476       value_peek_pointer0,      /* value_peek_pointer */
477       "p",                      /* collect_format */
478       value_collect_pointer,    /* collect_value */
479       "p",                      /* lcopy_format */
480       value_lcopy_pointer,      /* lcopy_value */
481     };
482     info.value_table = &value_table;
483     type = g_type_register_fundamental (G_TYPE_POINTER, "gpointer", &info, &finfo, 0);
484     g_assert (type == G_TYPE_POINTER);
485   }
486 }
487
488
489 /* --- GValue functions --- */
490 void
491 g_value_set_char (GValue *value,
492                   gchar   v_char)
493 {
494   g_return_if_fail (G_VALUE_HOLDS_CHAR (value));
495   
496   value->data[0].v_int = v_char;
497 }
498
499 gchar
500 g_value_get_char (const GValue *value)
501 {
502   g_return_val_if_fail (G_VALUE_HOLDS_CHAR (value), 0);
503   
504   return value->data[0].v_int;
505 }
506
507 void
508 g_value_set_uchar (GValue *value,
509                    guchar  v_uchar)
510 {
511   g_return_if_fail (G_VALUE_HOLDS_UCHAR (value));
512   
513   value->data[0].v_uint = v_uchar;
514 }
515
516 guchar
517 g_value_get_uchar (const GValue *value)
518 {
519   g_return_val_if_fail (G_VALUE_HOLDS_UCHAR (value), 0);
520   
521   return value->data[0].v_uint;
522 }
523
524 void
525 g_value_set_boolean (GValue  *value,
526                      gboolean v_boolean)
527 {
528   g_return_if_fail (G_VALUE_HOLDS_BOOLEAN (value));
529   
530   value->data[0].v_int = v_boolean != FALSE;
531 }
532
533 gboolean
534 g_value_get_boolean (const GValue *value)
535 {
536   g_return_val_if_fail (G_VALUE_HOLDS_BOOLEAN (value), 0);
537   
538   return value->data[0].v_int;
539 }
540
541 void
542 g_value_set_int (GValue *value,
543                  gint    v_int)
544 {
545   g_return_if_fail (G_VALUE_HOLDS_INT (value));
546   
547   value->data[0].v_int = v_int;
548 }
549
550 gint
551 g_value_get_int (const GValue *value)
552 {
553   g_return_val_if_fail (G_VALUE_HOLDS_INT (value), 0);
554   
555   return value->data[0].v_int;
556 }
557
558 void
559 g_value_set_uint (GValue *value,
560                   guint   v_uint)
561 {
562   g_return_if_fail (G_VALUE_HOLDS_UINT (value));
563   
564   value->data[0].v_uint = v_uint;
565 }
566
567 guint
568 g_value_get_uint (const GValue *value)
569 {
570   g_return_val_if_fail (G_VALUE_HOLDS_UINT (value), 0);
571   
572   return value->data[0].v_uint;
573 }
574
575 void
576 g_value_set_long (GValue *value,
577                   glong   v_long)
578 {
579   g_return_if_fail (G_VALUE_HOLDS_LONG (value));
580   
581   value->data[0].v_long = v_long;
582 }
583
584 glong
585 g_value_get_long (const GValue *value)
586 {
587   g_return_val_if_fail (G_VALUE_HOLDS_LONG (value), 0);
588   
589   return value->data[0].v_long;
590 }
591
592 void
593 g_value_set_ulong (GValue *value,
594                    gulong  v_ulong)
595 {
596   g_return_if_fail (G_VALUE_HOLDS_ULONG (value));
597   
598   value->data[0].v_ulong = v_ulong;
599 }
600
601 gulong
602 g_value_get_ulong (const GValue *value)
603 {
604   g_return_val_if_fail (G_VALUE_HOLDS_ULONG (value), 0);
605   
606   return value->data[0].v_ulong;
607 }
608
609 void
610 g_value_set_float (GValue *value,
611                    gfloat  v_float)
612 {
613   g_return_if_fail (G_VALUE_HOLDS_FLOAT (value));
614   
615   value->data[0].v_float = v_float;
616 }
617
618 gfloat
619 g_value_get_float (const GValue *value)
620 {
621   g_return_val_if_fail (G_VALUE_HOLDS_FLOAT (value), 0);
622   
623   return value->data[0].v_float;
624 }
625
626 void
627 g_value_set_double (GValue *value,
628                     gdouble v_double)
629 {
630   g_return_if_fail (G_VALUE_HOLDS_DOUBLE (value));
631   
632   value->data[0].v_double = v_double;
633 }
634
635 gdouble
636 g_value_get_double (const GValue *value)
637 {
638   g_return_val_if_fail (G_VALUE_HOLDS_DOUBLE (value), 0);
639   
640   return value->data[0].v_double;
641 }
642
643 void
644 g_value_set_string (GValue      *value,
645                     const gchar *v_string)
646 {
647   g_return_if_fail (G_VALUE_HOLDS_STRING (value));
648   
649   if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
650     value->data[1].v_uint = 0;
651   else
652     g_free (value->data[0].v_pointer);
653   value->data[0].v_pointer = g_strdup (v_string);
654 }
655
656 void
657 g_value_set_static_string (GValue      *value,
658                            const gchar *v_string)
659 {
660   g_return_if_fail (G_VALUE_HOLDS_STRING (value));
661   
662   if (!(value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS))
663     g_free (value->data[0].v_pointer);
664   value->data[1].v_uint = G_VALUE_NOCOPY_CONTENTS;
665   value->data[0].v_pointer = (gchar*) v_string;
666 }
667
668 void
669 g_value_set_string_take_ownership (GValue *value,
670                                    gchar  *v_string)
671 {
672   g_return_if_fail (G_VALUE_HOLDS_STRING (value));
673   
674   if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
675     value->data[1].v_uint = 0;
676   else
677     g_free (value->data[0].v_pointer);
678   value->data[0].v_pointer = v_string;
679 }
680
681 G_CONST_RETURN gchar*
682 g_value_get_string (const GValue *value)
683 {
684   g_return_val_if_fail (G_VALUE_HOLDS_STRING (value), NULL);
685   
686   return value->data[0].v_pointer;
687 }
688
689 gchar*
690 g_value_dup_string (const GValue *value)
691 {
692   g_return_val_if_fail (G_VALUE_HOLDS_STRING (value), NULL);
693   
694   return g_strdup (value->data[0].v_pointer);
695 }
696
697 void
698 g_value_set_pointer (GValue  *value,
699                      gpointer v_pointer)
700 {
701   g_return_if_fail (G_VALUE_HOLDS_POINTER (value));
702
703   value->data[0].v_pointer = v_pointer;
704 }
705
706 gpointer
707 g_value_get_pointer (const GValue *value)
708 {
709   g_return_val_if_fail (G_VALUE_HOLDS_POINTER (value), NULL);
710
711   return value->data[0].v_pointer;
712 }