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 void g_dataset_alloc_key (const gchar *string,
59 /* --- variables --- */
60 static GHashTable *g_dataset_location_ht = NULL;
61 static GHashTable *g_dataset_key_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;
65 static gchar **g_dataset_key_array = NULL;
66 static guint g_dataset_seq_id = 0;
70 /* --- functions --- */
71 static inline GDataset*
72 g_dataset_lookup (gconstpointer dataset_location)
74 register GDataset *dataset;
76 if (g_dataset_cached && g_dataset_cached->location == dataset_location)
77 return g_dataset_cached;
79 if (!g_dataset_location_ht)
80 g_dataset_initialize ();
82 dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
84 g_dataset_cached = dataset;
90 g_dataset_destroy_i (GDataset *dataset)
92 register GDatasetData *list;
94 if (dataset == g_dataset_cached)
95 g_dataset_cached = NULL;
96 g_hash_table_remove (g_dataset_location_ht, dataset->location);
98 list = dataset->data_list;
99 g_mem_chunk_free (g_dataset_mem_chunk, dataset);
103 register GDatasetData *prev;
108 if (prev->destroy_func)
109 prev->destroy_func (prev->data);
111 g_mem_chunk_free (g_dataset_data_mem_chunk, prev);
116 g_dataset_destroy (gconstpointer dataset_location)
118 register GDataset *dataset;
120 g_return_if_fail (dataset_location != NULL);
122 dataset = g_dataset_lookup (dataset_location);
124 g_dataset_destroy_i (dataset);
128 g_dataset_id_set_destroy (gconstpointer dataset_location,
130 GDestroyNotify destroy_func)
132 g_return_if_fail (dataset_location != NULL);
136 register GDataset *dataset;
138 dataset = g_dataset_lookup (dataset_location);
141 register GDatasetData *list;
143 list = dataset->data_list;
146 if (list->id == key_id)
148 list->destroy_func = destroy_func;
157 g_dataset_id_get_data (gconstpointer dataset_location,
160 g_return_val_if_fail (dataset_location != NULL, NULL);
164 register GDataset *dataset;
166 dataset = g_dataset_lookup (dataset_location);
169 register GDatasetData *list;
171 for (list = dataset->data_list; list; list = list->next)
172 if (list->id == key_id)
181 g_dataset_id_set_data_full (gconstpointer dataset_location,
184 GDestroyNotify destroy_func)
186 register GDataset *dataset;
187 register GDatasetData *list;
189 g_return_if_fail (dataset_location != NULL);
190 g_return_if_fail (key_id > 0);
192 dataset = g_dataset_lookup (dataset_location);
195 dataset = g_chunk_new (GDataset, g_dataset_mem_chunk);
196 dataset->location = dataset_location;
197 dataset->data_list = NULL;
198 g_hash_table_insert (g_dataset_location_ht,
199 (gpointer) dataset->location, /* Yuck */
203 list = dataset->data_list;
206 register GDatasetData *prev;
211 if (list->id == key_id)
214 prev->next = list->next;
217 dataset->data_list = list->next;
219 if (!dataset->data_list)
220 g_dataset_destroy_i (dataset);
223 /* we need to have unlinked before invoking the destroy function
225 if (list->destroy_func)
226 list->destroy_func (list->data);
228 g_mem_chunk_free (g_dataset_data_mem_chunk, list);
238 register GDatasetData *prev;
243 if (list->id == key_id)
246 prev->next = list->next;
248 dataset->data_list = list->next;
250 /* we need to have unlinked before invoking the destroy function
252 if (list->destroy_func)
253 list->destroy_func (list->data);
263 list = g_chunk_new (GDatasetData, g_dataset_data_mem_chunk);
264 list->next = dataset->data_list;
267 list->destroy_func = destroy_func;
268 dataset->data_list = list;
273 g_dataset_try_key (const gchar *key)
276 g_return_val_if_fail (key != NULL, 0);
278 if (g_dataset_key_ht)
280 id = g_hash_table_lookup (g_dataset_key_ht, (gpointer) key);
290 g_dataset_force_id (const gchar *key)
294 g_return_val_if_fail (key != NULL, 0);
296 if (!g_dataset_key_ht)
297 g_dataset_initialize ();
299 id = g_hash_table_lookup (g_dataset_key_ht, (gpointer) key);
304 g_dataset_alloc_key (key, &id, &new_key);
305 g_hash_table_insert (g_dataset_key_ht, new_key, id);
312 g_dataset_initialize (void)
314 if (!g_dataset_location_ht)
316 g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
317 g_dataset_key_ht = g_hash_table_new (g_str_hash, g_str_equal);
318 g_dataset_cached = NULL;
319 g_dataset_mem_chunk =
320 g_mem_chunk_new ("GDataset MemChunk",
322 sizeof (GDataset) * G_DATASET_MEM_CHUNK_PREALLOC,
324 g_dataset_data_mem_chunk =
325 g_mem_chunk_new ("GDatasetData MemChunk",
326 sizeof (GDatasetData),
327 sizeof (GDatasetData) * G_DATASET_DATA_MEM_CHUNK_PREALLOC,
333 g_dataset_retrive_key (guint id)
335 if (id > 0 && id <= g_dataset_seq_id)
336 return g_dataset_key_array[id - 1];
341 g_dataset_alloc_key (const gchar *string,
345 if (g_dataset_seq_id % G_DATASET_BLOCK_SIZE == 0)
346 g_dataset_key_array = g_realloc (g_dataset_key_array,
347 (g_dataset_seq_id + G_DATASET_BLOCK_SIZE) * sizeof (gchar*));
349 *key = g_new (gchar, sizeof (guint) + strlen (string) + 1);
351 *key += sizeof (guint);
352 strcpy (*key, string);
353 g_dataset_key_array[g_dataset_seq_id] = *key;
355 **id = g_dataset_seq_id;