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.
26 #define G_DATASET_ID_BLOCK_SIZE (1024)
27 #define G_DATASET_MEM_CHUNK_PREALLOC (512)
28 #define G_DATASET_DATA_MEM_CHUNK_PREALLOC (1024)
31 /* --- structures --- */
32 typedef struct _GDatasetData GDatasetData;
33 typedef struct _GDataset GDataset;
39 GDestroyNotify destroy_func;
44 gconstpointer location;
45 GDatasetData *data_list;
49 /* --- prototypes --- */
50 static inline GDataset* g_dataset_lookup (gconstpointer dataset_location);
51 static inline void g_dataset_destroy_i (GDataset *dataset);
52 static void g_dataset_initialize (void);
53 static guint* g_dataset_id_new (void);
56 /* --- variables --- */
57 static GHashTable *g_dataset_location_ht = NULL;
58 static GHashTable *g_dataset_key_ht = NULL;
59 static GDataset *g_dataset_cached = NULL;
60 static GMemChunk *g_dataset_mem_chunk = NULL;
61 static GMemChunk *g_dataset_data_mem_chunk = NULL;
62 static guint *g_dataset_id_block = NULL;
63 static guint g_dataset_id_index = G_DATASET_ID_BLOCK_SIZE + 1;
66 /* --- functions --- */
67 static inline GDataset*
68 g_dataset_lookup (gconstpointer dataset_location)
70 register GDataset *dataset;
72 if (g_dataset_cached && g_dataset_cached->location == dataset_location)
73 return g_dataset_cached;
75 if (!g_dataset_location_ht)
76 g_dataset_initialize ();
78 dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
80 g_dataset_cached = dataset;
86 g_dataset_destroy_i (GDataset *dataset)
88 register GDatasetData *list;
90 if (dataset == g_dataset_cached)
91 g_dataset_cached = NULL;
92 g_hash_table_remove (g_dataset_location_ht, dataset->location);
94 list = dataset->data_list;
95 g_mem_chunk_free (g_dataset_mem_chunk, dataset);
99 register GDatasetData *prev;
104 if (prev->destroy_func)
105 prev->destroy_func (prev->data);
107 g_mem_chunk_free (g_dataset_data_mem_chunk, prev);
112 g_dataset_destroy (gconstpointer dataset_location)
114 register GDataset *dataset;
116 g_return_if_fail (dataset_location != NULL);
118 dataset = g_dataset_lookup (dataset_location);
120 g_dataset_destroy_i (dataset);
124 g_dataset_id_set_destroy (gconstpointer dataset_location,
126 GDestroyNotify destroy_func)
128 g_return_if_fail (dataset_location != NULL);
132 register GDataset *dataset;
134 dataset = g_dataset_lookup (dataset_location);
137 register GDatasetData *list;
139 list = dataset->data_list;
142 if (list->id == key_id)
144 list->destroy_func = destroy_func;
153 g_dataset_id_get_data (gconstpointer dataset_location,
156 g_return_val_if_fail (dataset_location != NULL, NULL);
160 register GDataset *dataset;
162 dataset = g_dataset_lookup (dataset_location);
165 register GDatasetData *list;
167 for (list = dataset->data_list; list; list = list->next)
168 if (list->id == key_id)
177 g_dataset_id_set_data_full (gconstpointer dataset_location,
180 GDestroyNotify destroy_func)
182 register GDataset *dataset;
183 register GDatasetData *list;
185 g_return_if_fail (dataset_location != NULL);
186 g_return_if_fail (key_id > 0);
188 dataset = g_dataset_lookup (dataset_location);
191 dataset = g_chunk_new (GDataset, g_dataset_mem_chunk);
192 dataset->location = dataset_location;
193 dataset->data_list = NULL;
194 g_hash_table_insert (g_dataset_location_ht,
195 (gpointer) dataset->location, /* Yuck */
199 list = dataset->data_list;
202 register GDatasetData *prev;
207 if (list->id == key_id)
210 prev->next = list->next;
213 dataset->data_list = list->next;
215 if (!dataset->data_list)
216 g_dataset_destroy_i (dataset);
219 /* we need to have unlinked before invoking the destroy function
221 if (list->destroy_func)
222 list->destroy_func (list->data);
224 g_mem_chunk_free (g_dataset_data_mem_chunk, list);
234 register GDatasetData *prev;
239 if (list->id == key_id)
242 prev->next = list->next;
244 dataset->data_list = list->next;
246 /* we need to have unlinked before invoking the destroy function
248 if (list->destroy_func)
249 list->destroy_func (list->data);
259 list = g_chunk_new (GDatasetData, g_dataset_data_mem_chunk);
260 list->next = dataset->data_list;
263 list->destroy_func = destroy_func;
264 dataset->data_list = list;
269 g_dataset_try_key (const gchar *key)
272 g_return_val_if_fail (key != NULL, 0);
274 if (g_dataset_key_ht)
276 id = g_hash_table_lookup (g_dataset_key_ht, (gpointer) key);
286 g_dataset_force_id (const gchar *key)
290 g_return_val_if_fail (key != NULL, 0);
292 if (!g_dataset_key_ht)
293 g_dataset_initialize ();
295 id = g_hash_table_lookup (g_dataset_key_ht, (gpointer) key);
298 id = g_dataset_id_new ();
299 g_hash_table_insert (g_dataset_key_ht, g_strdup (key), id);
306 g_dataset_initialize (void)
308 if (!g_dataset_location_ht)
310 g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
311 g_dataset_key_ht = g_hash_table_new (g_str_hash, g_str_equal);
312 g_dataset_cached = NULL;
313 g_dataset_mem_chunk =
314 g_mem_chunk_new ("GDataset MemChunk",
316 sizeof (GDataset) * G_DATASET_MEM_CHUNK_PREALLOC,
318 g_dataset_data_mem_chunk =
319 g_mem_chunk_new ("GDatasetData MemChunk",
320 sizeof (GDatasetData),
321 sizeof (GDatasetData) * G_DATASET_DATA_MEM_CHUNK_PREALLOC,
327 g_dataset_id_new (void)
329 static guint seq_id = 1;
332 if (g_dataset_id_index >= G_DATASET_ID_BLOCK_SIZE)
334 g_dataset_id_block = g_new (guint, G_DATASET_ID_BLOCK_SIZE);
335 g_dataset_id_index = 0;
338 id = &g_dataset_id_block[g_dataset_id_index++];