]> Pileus Git - ~andy/gtk/blob - gtk/gtktreedatalist.c
updated for win32 msvc build
[~andy/gtk] / gtk / gtktreedatalist.c
1 /* gtktreedatalist.c
2  * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb@redhat.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "gtktreedatalist.h"
21 #include "gobject/gboxed.h"
22 #include "gobject/gvalue.h"
23 #include "gobject/gvaluetypes.h"
24
25 /* node allocation
26  */
27 struct _GAllocator /* from gmem.c */
28 {
29   gchar           *name;
30   guint16          n_preallocs;
31   guint            is_unused : 1;
32   guint            type : 4;
33   GAllocator      *last;
34   GMemChunk       *mem_chunk;
35   GtkTreeDataList *free_nodes;
36 };
37
38
39 G_LOCK_DEFINE_STATIC (current_allocator);
40 static GAllocator *current_allocator = NULL;
41
42 /* HOLDS: current_allocator_lock */
43 static void
44 gtk_tree_data_list_validate_allocator (GAllocator *allocator)
45 {
46   g_return_if_fail (allocator != NULL);
47   g_return_if_fail (allocator->is_unused == TRUE);
48
49   if (allocator->type != G_ALLOCATOR_NODE)
50     {
51       allocator->type = G_ALLOCATOR_NODE;
52       if (allocator->mem_chunk)
53         {
54           g_mem_chunk_destroy (allocator->mem_chunk);
55           allocator->mem_chunk = NULL;
56         }
57     }
58
59   if (!allocator->mem_chunk)
60     {
61       allocator->mem_chunk = g_mem_chunk_new (allocator->name,
62                                               sizeof (GtkTreeDataList),
63                                               sizeof (GtkTreeDataList) * allocator->n_preallocs,
64                                               G_ALLOC_ONLY);
65       allocator->free_nodes = NULL;
66     }
67
68   allocator->is_unused = FALSE;
69 }
70
71 void
72 _gtk_tree_data_list_push_allocator (GAllocator *allocator)
73 {
74   G_LOCK (current_allocator);
75   gtk_tree_data_list_validate_allocator ( allocator );
76   allocator->last = current_allocator;
77   current_allocator = allocator;
78   G_UNLOCK (current_allocator);
79 }
80
81 void
82 _gtk_tree_data_list_pop_allocator (void)
83 {
84   G_LOCK (current_allocator);
85   if (current_allocator)
86     {
87       GAllocator *allocator;
88
89       allocator = current_allocator;
90       current_allocator = allocator->last;
91       allocator->last = NULL;
92       allocator->is_unused = TRUE;
93     }
94   G_UNLOCK (current_allocator);
95 }
96
97 GtkTreeDataList *
98 _gtk_tree_data_list_alloc (void)
99 {
100   GtkTreeDataList *list;
101
102   G_LOCK (current_allocator);
103   if (!current_allocator)
104     {
105        GAllocator *allocator = g_allocator_new ("GTK+ default GtkTreeDataList allocator",
106                                                 128);
107        gtk_tree_data_list_validate_allocator (allocator);
108        allocator->last = NULL;
109        current_allocator = allocator;
110     }
111   if (!current_allocator->free_nodes)
112     list = g_chunk_new (GtkTreeDataList, current_allocator->mem_chunk);
113   else
114     {
115       list = current_allocator->free_nodes;
116       current_allocator->free_nodes = list->next;
117     }
118   G_UNLOCK (current_allocator);
119
120   return list;
121 }
122
123 void
124 _gtk_tree_data_list_free (GtkTreeDataList *list,
125                           GType           *column_headers)
126 {
127   GtkTreeDataList *tmp;
128   gint i = 0;
129
130   for (tmp = list; tmp; tmp = tmp->next)
131     {
132       switch (column_headers [i])
133         {
134         case G_TYPE_STRING:
135           g_free ((gchar *) tmp->data.v_pointer);
136           break;
137         case G_TYPE_OBJECT:
138           g_object_unref (G_OBJECT (tmp->data.v_pointer));
139           break;
140         default:
141           break;
142         }
143       i++;
144     }
145
146   G_LOCK (current_allocator);
147   list->next = current_allocator->free_nodes;
148   current_allocator->free_nodes = list;
149   G_UNLOCK (current_allocator);
150 }
151
152 void
153 _gtk_tree_data_list_node_to_value (GtkTreeDataList *list,
154                                    GType            type,
155                                    GValue          *value)
156 {
157   g_value_init (value, type);
158
159   switch (type)
160     {
161     case G_TYPE_BOOLEAN:
162       g_value_set_boolean (value, (gboolean) list->data.v_int);
163       break;
164     case G_TYPE_CHAR:
165       g_value_set_char (value, list->data.v_char);
166       break;
167     case G_TYPE_UCHAR:
168       g_value_set_uchar (value, list->data.v_uchar);
169       break;
170     case G_TYPE_INT:
171       g_value_set_int (value, list->data.v_int);
172       break;
173     case G_TYPE_UINT:
174       g_value_set_uint (value, list->data.v_uint);
175       break;
176     case G_TYPE_POINTER:
177       g_value_set_pointer (value, (gpointer) list->data.v_pointer);
178       break;
179     case G_TYPE_FLOAT:
180       g_value_set_float (value, list->data.v_float);
181       break;
182     case G_TYPE_STRING:
183       g_value_set_string (value, (gchar *) list->data.v_pointer);
184       break;
185
186     default:
187       if (g_type_is_a (type, G_TYPE_OBJECT))
188         g_value_set_object (value, (GObject *) list->data.v_pointer);
189       else if (g_type_is_a (type, G_TYPE_BOXED))
190         g_value_set_boxed (value, (GObject *) list->data.v_pointer);
191       else
192         g_warning ("Unsupported type (%s) retrieved.", g_type_name (value->g_type));
193       break;
194     }
195 }
196
197 void
198 _gtk_tree_data_list_value_to_node (GtkTreeDataList *list,
199                                    GValue          *value)
200 {
201   switch (value->g_type)
202     {
203     case G_TYPE_BOOLEAN:
204       list->data.v_int = g_value_get_boolean (value);
205       break;
206     case G_TYPE_CHAR:
207       list->data.v_char = g_value_get_char (value);
208       break;
209     case G_TYPE_UCHAR:
210       list->data.v_uchar = g_value_get_uchar (value);
211       break;
212     case G_TYPE_INT:
213       list->data.v_int = g_value_get_int (value);
214       break;
215     case G_TYPE_UINT:
216       list->data.v_uint = g_value_get_uint (value);
217       break;
218     case G_TYPE_POINTER:
219       list->data.v_pointer = g_value_get_pointer (value);
220       break;
221     case G_TYPE_FLOAT:
222       list->data.v_float = g_value_get_float (value);
223       break;
224     case G_TYPE_STRING:
225       list->data.v_pointer = g_value_dup_string (value);
226       break;
227     default:
228       if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_OBJECT))
229         list->data.v_pointer = g_value_dup_object (value);
230       else if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_BOXED))
231         list->data.v_pointer = g_value_dup_boxed (value);
232       else
233         g_warning ("Unsupported type (%s) stored.", g_type_name (value->g_type));
234       break;
235     }
236 }
237
238 GtkTreeDataList*
239 _gtk_tree_data_list_node_copy (GtkTreeDataList *list,
240                                GType            type)
241 {
242   GtkTreeDataList *new_list;
243
244   g_return_val_if_fail (list != NULL, NULL);
245   
246   new_list = _gtk_tree_data_list_alloc ();
247   new_list->next = NULL;
248   
249   switch (type)
250     {
251     case G_TYPE_UINT:
252     case G_TYPE_INT:
253     case G_TYPE_UCHAR:      
254     case G_TYPE_CHAR:
255     case G_TYPE_BOOLEAN:
256     case G_TYPE_POINTER:
257     case G_TYPE_FLOAT:
258       new_list->data = list->data;
259       break;
260
261     case G_TYPE_STRING:
262       new_list->data.v_pointer = g_strdup (list->data.v_pointer);
263       break;
264       
265     default:
266       if (g_type_is_a (type, G_TYPE_OBJECT))
267         {
268           new_list->data.v_pointer = list->data.v_pointer;
269           if (new_list->data.v_pointer)
270             g_object_ref (G_OBJECT (new_list->data.v_pointer));
271         }
272       else if (g_type_is_a (type, G_TYPE_BOXED))
273         {
274           if (list->data.v_pointer)
275             new_list->data.v_pointer = g_boxed_copy (type, list->data.v_pointer);
276           else
277             new_list->data.v_pointer = NULL;
278         }
279       else
280         g_warning ("Unsupported node type (%s) copied.", g_type_name (type));
281       break;
282     }
283   
284   return new_list;
285 }
286
287
288