1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * gdataset.c: Generic dataset mechanism, similar to GtkObject data.
5 * Copyright (C) 1998 Tim Janik
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
27 #define G_DATASET_BLOCK_SIZE (512)
28 #define G_DATASET_MEM_CHUNK_PREALLOC (64)
29 #define G_DATASET_DATA_MEM_CHUNK_PREALLOC (128)
32 /* --- structures --- */
33 typedef struct _GDatasetData GDatasetData;
34 typedef struct _GDataset GDataset;
40 GDestroyNotify destroy_func;
45 gconstpointer location;
46 GDatasetData *data_list;
50 /* --- prototypes --- */
51 static inline GDataset* g_dataset_lookup (gconstpointer dataset_location);
52 static inline void g_dataset_destroy_i (GDataset *dataset);
53 static void g_dataset_initialize (void);
54 static inline GQuark g_quark_new (const gchar *string);
57 /* --- variables --- */
58 static GHashTable *g_quark_ht = NULL;
59 static gchar **g_quarks = NULL;
60 static GQuark g_quark_seq_id = 0;
61 static GHashTable *g_dataset_location_ht = NULL;
62 static GDataset *g_dataset_cached = NULL;
63 static GMemChunk *g_dataset_mem_chunk = NULL;
64 static GMemChunk *g_dataset_data_mem_chunk = NULL;
68 /* --- functions --- */
69 static inline GDataset*
70 g_dataset_lookup (gconstpointer dataset_location)
72 register GDataset *dataset;
74 if (g_dataset_cached && g_dataset_cached->location == dataset_location)
75 return g_dataset_cached;
77 if (!g_dataset_location_ht)
78 g_dataset_initialize ();
80 dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
82 g_dataset_cached = dataset;
88 g_dataset_destroy_i (GDataset *dataset)
90 register GDatasetData *list;
92 if (dataset == g_dataset_cached)
93 g_dataset_cached = NULL;
94 g_hash_table_remove (g_dataset_location_ht, dataset->location);
96 list = dataset->data_list;
97 g_mem_chunk_free (g_dataset_mem_chunk, dataset);
101 register GDatasetData *prev;
106 if (prev->destroy_func)
107 prev->destroy_func (prev->data);
109 g_mem_chunk_free (g_dataset_data_mem_chunk, prev);
114 g_dataset_destroy (gconstpointer dataset_location)
116 register GDataset *dataset;
118 g_return_if_fail (dataset_location != NULL);
120 dataset = g_dataset_lookup (dataset_location);
122 g_dataset_destroy_i (dataset);
126 g_dataset_id_set_destroy (gconstpointer dataset_location,
128 GDestroyNotify destroy_func)
130 g_return_if_fail (dataset_location != NULL);
134 register GDataset *dataset;
136 dataset = g_dataset_lookup (dataset_location);
139 register GDatasetData *list;
141 list = dataset->data_list;
144 if (list->id == key_id)
146 list->destroy_func = destroy_func;
155 g_dataset_id_get_data (gconstpointer dataset_location,
158 g_return_val_if_fail (dataset_location != NULL, NULL);
162 register GDataset *dataset;
164 dataset = g_dataset_lookup (dataset_location);
167 register GDatasetData *list;
169 for (list = dataset->data_list; list; list = list->next)
170 if (list->id == key_id)
179 g_dataset_id_set_data_full (gconstpointer dataset_location,
182 GDestroyNotify destroy_func)
184 register GDataset *dataset;
185 register GDatasetData *list;
187 g_return_if_fail (dataset_location != NULL);
188 g_return_if_fail (key_id > 0);
190 dataset = g_dataset_lookup (dataset_location);
193 dataset = g_chunk_new (GDataset, g_dataset_mem_chunk);
194 dataset->location = dataset_location;
195 dataset->data_list = NULL;
196 g_hash_table_insert (g_dataset_location_ht,
197 (gpointer) dataset->location, /* Yuck */
201 list = dataset->data_list;
204 register GDatasetData *prev;
209 if (list->id == key_id)
212 prev->next = list->next;
215 dataset->data_list = list->next;
217 if (!dataset->data_list)
218 g_dataset_destroy_i (dataset);
221 /* we need to have unlinked before invoking the destroy function
223 if (list->destroy_func)
224 list->destroy_func (list->data);
226 g_mem_chunk_free (g_dataset_data_mem_chunk, list);
239 if (list->id == key_id)
241 register GDestroyNotify dfunc;
242 register gpointer ddata;
244 dfunc = list->destroy_func;
247 list->destroy_func = destroy_func;
249 /* we need to have updated all structures prior to
250 * invokation of the destroy function
261 list = g_chunk_new (GDatasetData, g_dataset_data_mem_chunk);
262 list->next = dataset->data_list;
265 list->destroy_func = destroy_func;
266 dataset->data_list = list;
271 g_dataset_initialize (void)
273 if (!g_dataset_location_ht)
275 g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
276 g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
277 g_dataset_cached = NULL;
278 g_dataset_mem_chunk =
279 g_mem_chunk_new ("GDataset MemChunk",
281 sizeof (GDataset) * G_DATASET_MEM_CHUNK_PREALLOC,
283 g_dataset_data_mem_chunk =
284 g_mem_chunk_new ("GDatasetData MemChunk",
285 sizeof (GDatasetData),
286 sizeof (GDatasetData) * G_DATASET_DATA_MEM_CHUNK_PREALLOC,
292 g_quark_try_string (const gchar *string)
294 g_return_val_if_fail (string != NULL, 0);
297 return (gulong) g_hash_table_lookup (g_quark_ht, string);
303 g_quark_from_string (const gchar *string)
307 g_return_val_if_fail (string != NULL, 0);
310 g_dataset_initialize ();
312 quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
314 quark = g_quark_new (g_strdup (string));
320 g_quark_from_static_string (const gchar *string)
324 g_return_val_if_fail (string != NULL, 0);
327 g_dataset_initialize ();
329 quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
331 quark = g_quark_new (string);
337 g_quark_to_string (GQuark quark)
339 if (quark > 0 && quark <= g_quark_seq_id)
340 return g_quarks[quark - 1];
346 g_quark_new (const gchar *string)
350 if (g_quark_seq_id % G_DATASET_BLOCK_SIZE == 0)
351 g_quarks = g_realloc (g_quarks,
352 (g_quark_seq_id + G_DATASET_BLOCK_SIZE) * sizeof (gchar*));
355 g_quarks[g_quark_seq_id] = (gchar*) string;
357 quark = g_quark_seq_id;
358 g_hash_table_insert (g_quark_ht, (gchar*) string, GUINT_TO_POINTER (quark));