gmain: fix some silly code in a programmer-error case
[glib.git] / glib / gdataset.c
blobcd3a51eac6328c0ad46814ce99d71c6c086de8f3
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 Lesser 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 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser 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.
23 * Modified by the GLib Team and others 1997-2000. See the AUTHORS
24 * file for a list of people on the GLib Team. See the ChangeLog
25 * files for a list of changes. These files are distributed with
26 * GLib at ftp://ftp.gtk.org/pub/gtk/.
30 * MT safe ; except for g_data*_foreach()
33 #include "config.h"
35 #include <string.h>
37 #include "gdataset.h"
39 #include "gdatasetprivate.h"
40 #include "ghash.h"
41 #include "gquark.h"
42 #include "gstrfuncs.h"
43 #include "gtestutils.h"
44 #include "gthread.h"
45 #include "glib_trace.h"
47 /**
48 * SECTION: datasets
49 * @title: Datasets
50 * @short_description: associate groups of data elements with
51 * particular memory locations
53 * Datasets associate groups of data elements with particular memory
54 * locations. These are useful if you need to associate data with a
55 * structure returned from an external library. Since you cannot modify
56 * the structure, you use its location in memory as the key into a
57 * dataset, where you can associate any number of data elements with it.
59 * There are two forms of most of the dataset functions. The first form
60 * uses strings to identify the data elements associated with a
61 * location. The second form uses #GQuark identifiers, which are
62 * created with a call to g_quark_from_string() or
63 * g_quark_from_static_string(). The second form is quicker, since it
64 * does not require looking up the string in the hash table of #GQuark
65 * identifiers.
67 * There is no function to create a dataset. It is automatically
68 * created as soon as you add elements to it.
70 * To add data elements to a dataset use g_dataset_id_set_data(),
71 * g_dataset_id_set_data_full(), g_dataset_set_data() and
72 * g_dataset_set_data_full().
74 * To get data elements from a dataset use g_dataset_id_get_data() and
75 * g_dataset_get_data().
77 * To iterate over all data elements in a dataset use
78 * g_dataset_foreach() (not thread-safe).
80 * To remove data elements from a dataset use
81 * g_dataset_id_remove_data() and g_dataset_remove_data().
83 * To destroy a dataset, use g_dataset_destroy().
84 **/
86 /**
87 * SECTION: datalist
88 * @title: Keyed Data Lists
89 * @short_description: lists of data elements which are accessible by a
90 * string or GQuark identifier
92 * Keyed data lists provide lists of arbitrary data elements which can
93 * be accessed either with a string or with a #GQuark corresponding to
94 * the string.
96 * The #GQuark methods are quicker, since the strings have to be
97 * converted to #GQuarks anyway.
99 * Data lists are used for associating arbitrary data with #GObjects,
100 * using g_object_set_data() and related functions.
102 * To create a datalist, use g_datalist_init().
104 * To add data elements to a datalist use g_datalist_id_set_data(),
105 * g_datalist_id_set_data_full(), g_datalist_set_data() and
106 * g_datalist_set_data_full().
108 * To get data elements from a datalist use g_datalist_id_get_data()
109 * and g_datalist_get_data().
111 * To iterate over all data elements in a datalist use
112 * g_datalist_foreach() (not thread-safe).
114 * To remove data elements from a datalist use
115 * g_datalist_id_remove_data() and g_datalist_remove_data().
117 * To remove all data elements from a datalist, use g_datalist_clear().
121 * GData:
123 * The #GData struct is an opaque data structure to represent a <link
124 * linkend="glib-Keyed-Data-Lists">Keyed Data List</link>. It should
125 * only be accessed via the following functions.
129 * GDestroyNotify:
130 * @data: the data element.
132 * Specifies the type of function which is called when a data element
133 * is destroyed. It is passed the pointer to the data element and
134 * should free any memory and resources allocated for it.
137 /* --- defines --- */
138 #define G_QUARK_BLOCK_SIZE (512)
140 /* datalist pointer accesses have to be carried out atomically */
141 #define G_DATALIST_GET_POINTER(datalist) \
142 ((GData*) ((gsize) g_atomic_pointer_get (datalist) & ~(gsize) G_DATALIST_FLAGS_MASK))
144 #define G_DATALIST_SET_POINTER(datalist, pointer) G_STMT_START { \
145 gpointer _oldv, _newv; \
146 do { \
147 _oldv = g_atomic_pointer_get (datalist); \
148 _newv = (gpointer) (((gsize) _oldv & G_DATALIST_FLAGS_MASK) | (gsize) pointer); \
149 } while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, _oldv, _newv)); \
150 } G_STMT_END
152 /* --- structures --- */
153 typedef struct _GDataset GDataset;
154 struct _GData
156 GData *next;
157 GQuark id;
158 gpointer data;
159 GDestroyNotify destroy_func;
162 struct _GDataset
164 gconstpointer location;
165 GData *datalist;
169 /* --- prototypes --- */
170 static inline GDataset* g_dataset_lookup (gconstpointer dataset_location);
171 static inline void g_datalist_clear_i (GData **datalist);
172 static void g_dataset_destroy_internal (GDataset *dataset);
173 static inline gpointer g_data_set_internal (GData **datalist,
174 GQuark key_id,
175 gpointer data,
176 GDestroyNotify destroy_func,
177 GDataset *dataset);
178 static void g_data_initialize (void);
179 static inline GQuark g_quark_new (gchar *string);
182 /* --- variables --- */
183 G_LOCK_DEFINE_STATIC (g_dataset_global);
184 static GHashTable *g_dataset_location_ht = NULL;
185 static GDataset *g_dataset_cached = NULL; /* should this be
186 threadspecific? */
187 G_LOCK_DEFINE_STATIC (g_quark_global);
188 static GHashTable *g_quark_ht = NULL;
189 static gchar **g_quarks = NULL;
190 static GQuark g_quark_seq_id = 0;
192 /* --- functions --- */
194 /* HOLDS: g_dataset_global_lock */
195 static inline void
196 g_datalist_clear_i (GData **datalist)
198 register GData *list;
200 /* unlink *all* items before walking their destructors
202 list = G_DATALIST_GET_POINTER (datalist);
203 G_DATALIST_SET_POINTER (datalist, NULL);
205 while (list)
207 register GData *prev;
209 prev = list;
210 list = prev->next;
212 if (prev->destroy_func)
214 G_UNLOCK (g_dataset_global);
215 prev->destroy_func (prev->data);
216 G_LOCK (g_dataset_global);
219 g_slice_free (GData, prev);
224 * g_datalist_clear:
225 * @datalist: a datalist.
227 * Frees all the data elements of the datalist. The data elements'
228 * destroy functions are called if they have been set.
230 void
231 g_datalist_clear (GData **datalist)
233 g_return_if_fail (datalist != NULL);
235 G_LOCK (g_dataset_global);
236 if (!g_dataset_location_ht)
237 g_data_initialize ();
239 while (G_DATALIST_GET_POINTER (datalist))
240 g_datalist_clear_i (datalist);
241 G_UNLOCK (g_dataset_global);
244 /* HOLDS: g_dataset_global_lock */
245 static inline GDataset*
246 g_dataset_lookup (gconstpointer dataset_location)
248 register GDataset *dataset;
250 if (g_dataset_cached && g_dataset_cached->location == dataset_location)
251 return g_dataset_cached;
253 dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
254 if (dataset)
255 g_dataset_cached = dataset;
257 return dataset;
260 /* HOLDS: g_dataset_global_lock */
261 static void
262 g_dataset_destroy_internal (GDataset *dataset)
264 register gconstpointer dataset_location;
266 dataset_location = dataset->location;
267 while (dataset)
269 if (!dataset->datalist)
271 if (dataset == g_dataset_cached)
272 g_dataset_cached = NULL;
273 g_hash_table_remove (g_dataset_location_ht, dataset_location);
274 g_slice_free (GDataset, dataset);
275 break;
278 g_datalist_clear_i (&dataset->datalist);
279 dataset = g_dataset_lookup (dataset_location);
284 * g_dataset_destroy:
285 * @dataset_location: the location identifying the dataset.
287 * Destroys the dataset, freeing all memory allocated, and calling any
288 * destroy functions set for data elements.
290 void
291 g_dataset_destroy (gconstpointer dataset_location)
293 g_return_if_fail (dataset_location != NULL);
295 G_LOCK (g_dataset_global);
296 if (g_dataset_location_ht)
298 register GDataset *dataset;
300 dataset = g_dataset_lookup (dataset_location);
301 if (dataset)
302 g_dataset_destroy_internal (dataset);
304 G_UNLOCK (g_dataset_global);
307 /* HOLDS: g_dataset_global_lock */
308 static inline gpointer
309 g_data_set_internal (GData **datalist,
310 GQuark key_id,
311 gpointer data,
312 GDestroyNotify destroy_func,
313 GDataset *dataset)
315 register GData *list;
317 list = G_DATALIST_GET_POINTER (datalist);
318 if (!data)
320 register GData *prev;
322 prev = NULL;
323 while (list)
325 if (list->id == key_id)
327 gpointer ret_data = NULL;
329 if (prev)
330 prev->next = list->next;
331 else
333 G_DATALIST_SET_POINTER (datalist, list->next);
335 /* the dataset destruction *must* be done
336 * prior to invocation of the data destroy function
338 if (!list->next && dataset)
339 g_dataset_destroy_internal (dataset);
342 /* the GData struct *must* already be unlinked
343 * when invoking the destroy function.
344 * we use (data==NULL && destroy_func!=NULL) as
345 * a special hint combination to "steal"
346 * data without destroy notification
348 if (list->destroy_func && !destroy_func)
350 G_UNLOCK (g_dataset_global);
351 list->destroy_func (list->data);
352 G_LOCK (g_dataset_global);
354 else
355 ret_data = list->data;
357 g_slice_free (GData, list);
359 return ret_data;
362 prev = list;
363 list = list->next;
366 else
368 while (list)
370 if (list->id == key_id)
372 if (!list->destroy_func)
374 list->data = data;
375 list->destroy_func = destroy_func;
377 else
379 register GDestroyNotify dfunc;
380 register gpointer ddata;
382 dfunc = list->destroy_func;
383 ddata = list->data;
384 list->data = data;
385 list->destroy_func = destroy_func;
387 /* we need to have updated all structures prior to
388 * invocation of the destroy function
390 G_UNLOCK (g_dataset_global);
391 dfunc (ddata);
392 G_LOCK (g_dataset_global);
395 return NULL;
398 list = list->next;
401 list = g_slice_new (GData);
402 list->next = G_DATALIST_GET_POINTER (datalist);
403 list->id = key_id;
404 list->data = data;
405 list->destroy_func = destroy_func;
406 G_DATALIST_SET_POINTER (datalist, list);
409 return NULL;
413 * g_dataset_id_set_data_full:
414 * @dataset_location: the location identifying the dataset.
415 * @key_id: the #GQuark id to identify the data element.
416 * @data: the data element.
417 * @destroy_func: the function to call when the data element is
418 * removed. This function will be called with the data
419 * element and can be used to free any memory allocated
420 * for it.
422 * Sets the data element associated with the given #GQuark id, and also
423 * the function to call when the data element is destroyed. Any
424 * previous data with the same key is removed, and its destroy function
425 * is called.
428 * g_dataset_set_data_full:
429 * @l: the location identifying the dataset.
430 * @k: the string to identify the data element.
431 * @d: the data element.
432 * @f: the function to call when the data element is removed. This
433 * function will be called with the data element and can be used to
434 * free any memory allocated for it.
436 * Sets the data corresponding to the given string identifier, and the
437 * function to call when the data element is destroyed.
440 * g_dataset_id_set_data:
441 * @l: the location identifying the dataset.
442 * @k: the #GQuark id to identify the data element.
443 * @d: the data element.
445 * Sets the data element associated with the given #GQuark id. Any
446 * previous data with the same key is removed, and its destroy function
447 * is called.
450 * g_dataset_set_data:
451 * @l: the location identifying the dataset.
452 * @k: the string to identify the data element.
453 * @d: the data element.
455 * Sets the data corresponding to the given string identifier.
458 * g_dataset_id_remove_data:
459 * @l: the location identifying the dataset.
460 * @k: the #GQuark id identifying the data element.
462 * Removes a data element from a dataset. The data element's destroy
463 * function is called if it has been set.
466 * g_dataset_remove_data:
467 * @l: the location identifying the dataset.
468 * @k: the string identifying the data element.
470 * Removes a data element corresponding to a string. Its destroy
471 * function is called if it has been set.
473 void
474 g_dataset_id_set_data_full (gconstpointer dataset_location,
475 GQuark key_id,
476 gpointer data,
477 GDestroyNotify destroy_func)
479 register GDataset *dataset;
481 g_return_if_fail (dataset_location != NULL);
482 if (!data)
483 g_return_if_fail (destroy_func == NULL);
484 if (!key_id)
486 if (data)
487 g_return_if_fail (key_id > 0);
488 else
489 return;
492 G_LOCK (g_dataset_global);
493 if (!g_dataset_location_ht)
494 g_data_initialize ();
496 dataset = g_dataset_lookup (dataset_location);
497 if (!dataset)
499 dataset = g_slice_new (GDataset);
500 dataset->location = dataset_location;
501 g_datalist_init (&dataset->datalist);
502 g_hash_table_insert (g_dataset_location_ht,
503 (gpointer) dataset->location,
504 dataset);
507 g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
508 G_UNLOCK (g_dataset_global);
512 * g_datalist_id_set_data_full:
513 * @datalist: a datalist.
514 * @key_id: the #GQuark to identify the data element.
515 * @data: the data element or %NULL to remove any previous element
516 * corresponding to @key_id.
517 * @destroy_func: the function to call when the data element is
518 * removed. This function will be called with the data
519 * element and can be used to free any memory allocated
520 * for it. If @data is %NULL, then @destroy_func must
521 * also be %NULL.
523 * Sets the data corresponding to the given #GQuark id, and the
524 * function to be called when the element is removed from the datalist.
525 * Any previous data with the same key is removed, and its destroy
526 * function is called.
529 * g_datalist_set_data_full:
530 * @dl: a datalist.
531 * @k: the string to identify the data element.
532 * @d: the data element, or %NULL to remove any previous element
533 * corresponding to @k.
534 * @f: the function to call when the data element is removed. This
535 * function will be called with the data element and can be used to
536 * free any memory allocated for it. If @d is %NULL, then @f must
537 * also be %NULL.
539 * Sets the data element corresponding to the given string identifier,
540 * and the function to be called when the data element is removed.
543 * g_datalist_id_set_data:
544 * @dl: a datalist.
545 * @q: the #GQuark to identify the data element.
546 * @d: the data element, or %NULL to remove any previous element
547 * corresponding to @q.
549 * Sets the data corresponding to the given #GQuark id. Any previous
550 * data with the same key is removed, and its destroy function is
551 * called.
554 * g_datalist_set_data:
555 * @dl: a datalist.
556 * @k: the string to identify the data element.
557 * @d: the data element, or %NULL to remove any previous element
558 * corresponding to @k.
560 * Sets the data element corresponding to the given string identifier.
563 * g_datalist_id_remove_data:
564 * @dl: a datalist.
565 * @q: the #GQuark identifying the data element.
567 * Removes an element, using its #GQuark identifier.
570 * g_datalist_remove_data:
571 * @dl: a datalist.
572 * @k: the string identifying the data element.
574 * Removes an element using its string identifier. The data element's
575 * destroy function is called if it has been set.
577 void
578 g_datalist_id_set_data_full (GData **datalist,
579 GQuark key_id,
580 gpointer data,
581 GDestroyNotify destroy_func)
583 g_return_if_fail (datalist != NULL);
584 if (!data)
585 g_return_if_fail (destroy_func == NULL);
586 if (!key_id)
588 if (data)
589 g_return_if_fail (key_id > 0);
590 else
591 return;
594 G_LOCK (g_dataset_global);
595 if (!g_dataset_location_ht)
596 g_data_initialize ();
598 g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
599 G_UNLOCK (g_dataset_global);
603 * g_dataset_id_remove_no_notify:
604 * @dataset_location: the location identifying the dataset.
605 * @key_id: the #GQuark ID identifying the data element.
606 * @Returns: the data previously stored at @key_id, or %NULL if none.
608 * Removes an element, without calling its destroy notification
609 * function.
612 * g_dataset_remove_no_notify:
613 * @l: the location identifying the dataset.
614 * @k: the string identifying the data element.
616 * Removes an element, without calling its destroy notifier.
618 gpointer
619 g_dataset_id_remove_no_notify (gconstpointer dataset_location,
620 GQuark key_id)
622 gpointer ret_data = NULL;
624 g_return_val_if_fail (dataset_location != NULL, NULL);
626 G_LOCK (g_dataset_global);
627 if (key_id && g_dataset_location_ht)
629 GDataset *dataset;
631 dataset = g_dataset_lookup (dataset_location);
632 if (dataset)
633 ret_data = g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset);
635 G_UNLOCK (g_dataset_global);
637 return ret_data;
641 * g_datalist_id_remove_no_notify:
642 * @datalist: a datalist.
643 * @key_id: the #GQuark identifying a data element.
644 * @Returns: the data previously stored at @key_id, or %NULL if none.
646 * Removes an element, without calling its destroy notification
647 * function.
650 * g_datalist_remove_no_notify:
651 * @dl: a datalist.
652 * @k: the string identifying the data element.
654 * Removes an element, without calling its destroy notifier.
656 gpointer
657 g_datalist_id_remove_no_notify (GData **datalist,
658 GQuark key_id)
660 gpointer ret_data = NULL;
662 g_return_val_if_fail (datalist != NULL, NULL);
664 G_LOCK (g_dataset_global);
665 if (key_id && g_dataset_location_ht)
666 ret_data = g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
667 G_UNLOCK (g_dataset_global);
669 return ret_data;
673 * g_dataset_id_get_data:
674 * @dataset_location: the location identifying the dataset.
675 * @key_id: the #GQuark id to identify the data element.
676 * @Returns: the data element corresponding to the #GQuark, or %NULL if
677 * it is not found.
679 * Gets the data element corresponding to a #GQuark.
682 * g_dataset_get_data:
683 * @l: the location identifying the dataset.
684 * @k: the string identifying the data element.
685 * @Returns: the data element corresponding to the string, or %NULL if
686 * it is not found.
688 * Gets the data element corresponding to a string.
690 gpointer
691 g_dataset_id_get_data (gconstpointer dataset_location,
692 GQuark key_id)
694 g_return_val_if_fail (dataset_location != NULL, NULL);
696 G_LOCK (g_dataset_global);
697 if (key_id && g_dataset_location_ht)
699 register GDataset *dataset;
701 dataset = g_dataset_lookup (dataset_location);
702 if (dataset)
704 register GData *list;
706 for (list = dataset->datalist; list; list = list->next)
707 if (list->id == key_id)
709 G_UNLOCK (g_dataset_global);
710 return list->data;
714 G_UNLOCK (g_dataset_global);
716 return NULL;
720 * g_datalist_id_get_data:
721 * @datalist: a datalist.
722 * @key_id: the #GQuark identifying a data element.
723 * @Returns: the data element, or %NULL if it is not found.
725 * Retrieves the data element corresponding to @key_id.
728 * g_datalist_get_data:
729 * @dl: a datalist.
730 * @k: the string identifying a data element.
731 * @Returns: the data element, or %NULL if it is not found.
733 * Gets a data element, using its string identifer. This is slower than
734 * g_datalist_id_get_data() because the string is first converted to a
735 * #GQuark.
737 gpointer
738 g_datalist_id_get_data (GData **datalist,
739 GQuark key_id)
741 gpointer data = NULL;
742 g_return_val_if_fail (datalist != NULL, NULL);
743 if (key_id)
745 register GData *list;
746 G_LOCK (g_dataset_global);
747 for (list = G_DATALIST_GET_POINTER (datalist); list; list = list->next)
748 if (list->id == key_id)
750 data = list->data;
751 break;
753 G_UNLOCK (g_dataset_global);
755 return data;
759 * GDataForeachFunc:
760 * @key_id: the #GQuark id to identifying the data element.
761 * @data: the data element.
762 * @user_data: user data passed to g_dataset_foreach().
764 * Specifies the type of function passed to g_dataset_foreach(). It is
765 * called with each #GQuark id and associated data element, together
766 * with the @user_data parameter supplied to g_dataset_foreach().
770 * g_dataset_foreach:
771 * @dataset_location: the location identifying the dataset.
772 * @func: the function to call for each data element.
773 * @user_data: user data to pass to the function.
775 * Calls the given function for each data element which is associated
776 * with the given location. Note that this function is NOT thread-safe.
777 * So unless @datalist can be protected from any modifications during
778 * invocation of this function, it should not be called.
780 void
781 g_dataset_foreach (gconstpointer dataset_location,
782 GDataForeachFunc func,
783 gpointer user_data)
785 register GDataset *dataset;
787 g_return_if_fail (dataset_location != NULL);
788 g_return_if_fail (func != NULL);
790 G_LOCK (g_dataset_global);
791 if (g_dataset_location_ht)
793 dataset = g_dataset_lookup (dataset_location);
794 G_UNLOCK (g_dataset_global);
795 if (dataset)
797 register GData *list, *next;
799 for (list = dataset->datalist; list; list = next)
801 next = list->next;
802 func (list->id, list->data, user_data);
806 else
808 G_UNLOCK (g_dataset_global);
813 * g_datalist_foreach:
814 * @datalist: a datalist.
815 * @func: the function to call for each data element.
816 * @user_data: user data to pass to the function.
818 * Calls the given function for each data element of the datalist. The
819 * function is called with each data element's #GQuark id and data,
820 * together with the given @user_data parameter. Note that this
821 * function is NOT thread-safe. So unless @datalist can be protected
822 * from any modifications during invocation of this function, it should
823 * not be called.
825 void
826 g_datalist_foreach (GData **datalist,
827 GDataForeachFunc func,
828 gpointer user_data)
830 register GData *list, *next;
832 g_return_if_fail (datalist != NULL);
833 g_return_if_fail (func != NULL);
835 for (list = G_DATALIST_GET_POINTER (datalist); list; list = next)
837 next = list->next;
838 func (list->id, list->data, user_data);
843 * g_datalist_init:
844 * @datalist: a pointer to a pointer to a datalist.
846 * Resets the datalist to %NULL. It does not free any memory or call
847 * any destroy functions.
849 void
850 g_datalist_init (GData **datalist)
852 g_return_if_fail (datalist != NULL);
854 g_atomic_pointer_set (datalist, NULL);
858 * g_datalist_set_flags:
859 * @datalist: pointer to the location that holds a list
860 * @flags: the flags to turn on. The values of the flags are
861 * restricted by %G_DATALIST_FLAGS_MASK (currently
862 * 3; giving two possible boolean flags).
863 * A value for @flags that doesn't fit within the mask is
864 * an error.
866 * Turns on flag values for a data list. This function is used
867 * to keep a small number of boolean flags in an object with
868 * a data list without using any additional space. It is
869 * not generally useful except in circumstances where space
870 * is very tight. (It is used in the base #GObject type, for
871 * example.)
873 * Since: 2.8
875 void
876 g_datalist_set_flags (GData **datalist,
877 guint flags)
879 gpointer oldvalue;
880 g_return_if_fail (datalist != NULL);
881 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
885 oldvalue = g_atomic_pointer_get (datalist);
887 while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
888 (gpointer) ((gsize) oldvalue | flags)));
892 * g_datalist_unset_flags:
893 * @datalist: pointer to the location that holds a list
894 * @flags: the flags to turn off. The values of the flags are
895 * restricted by %G_DATALIST_FLAGS_MASK (currently
896 * 3: giving two possible boolean flags).
897 * A value for @flags that doesn't fit within the mask is
898 * an error.
900 * Turns off flag values for a data list. See g_datalist_unset_flags()
902 * Since: 2.8
904 void
905 g_datalist_unset_flags (GData **datalist,
906 guint flags)
908 gpointer oldvalue;
909 g_return_if_fail (datalist != NULL);
910 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
914 oldvalue = g_atomic_pointer_get (datalist);
916 while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
917 (gpointer) ((gsize) oldvalue & ~(gsize) flags)));
921 * g_datalist_get_flags:
922 * @datalist: pointer to the location that holds a list
924 * Gets flags values packed in together with the datalist.
925 * See g_datalist_set_flags().
927 * Return value: the flags of the datalist
929 * Since: 2.8
931 guint
932 g_datalist_get_flags (GData **datalist)
934 g_return_val_if_fail (datalist != NULL, 0);
936 return G_DATALIST_GET_FLAGS (datalist); /* atomic macro */
939 /* HOLDS: g_dataset_global_lock */
940 static void
941 g_data_initialize (void)
943 g_return_if_fail (g_dataset_location_ht == NULL);
945 g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
946 g_dataset_cached = NULL;
950 * SECTION: quarks
951 * @title: Quarks
952 * @short_description: a 2-way association between a string and a
953 * unique integer identifier
955 * Quarks are associations between strings and integer identifiers.
956 * Given either the string or the #GQuark identifier it is possible to
957 * retrieve the other.
959 * Quarks are used for both <link
960 * linkend="glib-datasets">Datasets</link> and <link
961 * linkend="glib-keyed-data-lists">Keyed Data Lists</link>.
963 * To create a new quark from a string, use g_quark_from_string() or
964 * g_quark_from_static_string().
966 * To find the string corresponding to a given #GQuark, use
967 * g_quark_to_string().
969 * To find the #GQuark corresponding to a given string, use
970 * g_quark_try_string().
972 * Another use for the string pool maintained for the quark functions
973 * is string interning, using g_intern_string() or
974 * g_intern_static_string(). An interned string is a canonical
975 * representation for a string. One important advantage of interned
976 * strings is that they can be compared for equality by a simple
977 * pointer comparision, rather than using strcmp().
981 * GQuark:
983 * A GQuark is a non-zero integer which uniquely identifies a
984 * particular string. A GQuark value of zero is associated to %NULL.
988 * g_quark_try_string:
989 * @string: a string.
990 * @Returns: the #GQuark associated with the string, or 0 if @string is
991 * %NULL or there is no #GQuark associated with it.
993 * Gets the #GQuark associated with the given string, or 0 if string is
994 * %NULL or it has no associated #GQuark.
996 * If you want the GQuark to be created if it doesn't already exist,
997 * use g_quark_from_string() or g_quark_from_static_string().
999 GQuark
1000 g_quark_try_string (const gchar *string)
1002 GQuark quark = 0;
1004 if (string == NULL)
1005 return 0;
1007 G_LOCK (g_quark_global);
1008 if (g_quark_ht)
1009 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1010 G_UNLOCK (g_quark_global);
1012 return quark;
1015 #define QUARK_STRING_BLOCK_SIZE (4096 - sizeof (gsize))
1016 static char *quark_block = NULL;
1017 static int quark_block_offset = 0;
1019 /* HOLDS: g_quark_global_lock */
1020 static char *
1021 quark_strdup(const gchar *string)
1023 gchar *copy;
1024 gsize len;
1026 len = strlen (string) + 1;
1028 /* For strings longer than half the block size, fall back
1029 to strdup so that we fill our blocks at least 50%. */
1030 if (len > QUARK_STRING_BLOCK_SIZE / 2)
1031 return g_strdup (string);
1033 if (quark_block == NULL ||
1034 QUARK_STRING_BLOCK_SIZE - quark_block_offset < len)
1036 quark_block = g_malloc (QUARK_STRING_BLOCK_SIZE);
1037 quark_block_offset = 0;
1040 copy = quark_block + quark_block_offset;
1041 memcpy (copy, string, len);
1042 quark_block_offset += len;
1044 return copy;
1047 /* HOLDS: g_quark_global_lock */
1048 static inline GQuark
1049 g_quark_from_string_internal (const gchar *string,
1050 gboolean duplicate)
1052 GQuark quark = 0;
1054 if (g_quark_ht)
1055 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1057 if (!quark)
1059 quark = g_quark_new (duplicate ? quark_strdup (string) : (gchar *)string);
1060 TRACE(GLIB_QUARK_NEW(string, quark));
1063 return quark;
1067 * g_quark_from_string:
1068 * @string: a string.
1069 * @Returns: the #GQuark identifying the string, or 0 if @string is
1070 * %NULL.
1072 * Gets the #GQuark identifying the given string. If the string does
1073 * not currently have an associated #GQuark, a new #GQuark is created,
1074 * using a copy of the string.
1076 GQuark
1077 g_quark_from_string (const gchar *string)
1079 GQuark quark;
1081 if (!string)
1082 return 0;
1084 G_LOCK (g_quark_global);
1085 quark = g_quark_from_string_internal (string, TRUE);
1086 G_UNLOCK (g_quark_global);
1088 return quark;
1092 * g_quark_from_static_string:
1093 * @string: a string.
1094 * @Returns: the #GQuark identifying the string, or 0 if @string is
1095 * %NULL.
1097 * Gets the #GQuark identifying the given (static) string. If the
1098 * string does not currently have an associated #GQuark, a new #GQuark
1099 * is created, linked to the given string.
1101 * Note that this function is identical to g_quark_from_string() except
1102 * that if a new #GQuark is created the string itself is used rather
1103 * than a copy. This saves memory, but can only be used if the string
1104 * will <emphasis>always</emphasis> exist. It can be used with
1105 * statically allocated strings in the main program, but not with
1106 * statically allocated memory in dynamically loaded modules, if you
1107 * expect to ever unload the module again (e.g. do not use this
1108 * function in GTK+ theme engines).
1110 GQuark
1111 g_quark_from_static_string (const gchar *string)
1113 GQuark quark;
1115 if (!string)
1116 return 0;
1118 G_LOCK (g_quark_global);
1119 quark = g_quark_from_string_internal (string, FALSE);
1120 G_UNLOCK (g_quark_global);
1122 return quark;
1126 * g_quark_to_string:
1127 * @quark: a #GQuark.
1128 * @Returns: the string associated with the #GQuark.
1130 * Gets the string associated with the given #GQuark.
1132 G_CONST_RETURN gchar*
1133 g_quark_to_string (GQuark quark)
1135 gchar* result = NULL;
1137 G_LOCK (g_quark_global);
1138 if (quark < g_quark_seq_id)
1139 result = g_quarks[quark];
1140 G_UNLOCK (g_quark_global);
1142 return result;
1145 /* HOLDS: g_quark_global_lock */
1146 static inline GQuark
1147 g_quark_new (gchar *string)
1149 GQuark quark;
1151 if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
1152 g_quarks = g_renew (gchar*, g_quarks, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
1153 if (!g_quark_ht)
1155 g_assert (g_quark_seq_id == 0);
1156 g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
1157 g_quarks[g_quark_seq_id++] = NULL;
1160 quark = g_quark_seq_id++;
1161 g_quarks[quark] = string;
1162 g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
1164 return quark;
1168 * g_intern_string:
1169 * @string: a string
1171 * Returns a canonical representation for @string. Interned strings can
1172 * be compared for equality by comparing the pointers, instead of using strcmp().
1174 * Returns: a canonical representation for the string
1176 * Since: 2.10
1178 G_CONST_RETURN gchar*
1179 g_intern_string (const gchar *string)
1181 const gchar *result;
1182 GQuark quark;
1184 if (!string)
1185 return NULL;
1187 G_LOCK (g_quark_global);
1188 quark = g_quark_from_string_internal (string, TRUE);
1189 result = g_quarks[quark];
1190 G_UNLOCK (g_quark_global);
1192 return result;
1196 * g_intern_static_string:
1197 * @string: a static string
1199 * Returns a canonical representation for @string. Interned strings can
1200 * be compared for equality by comparing the pointers, instead of using strcmp().
1201 * g_intern_static_string() does not copy the string, therefore @string must
1202 * not be freed or modified.
1204 * Returns: a canonical representation for the string
1206 * Since: 2.10
1208 G_CONST_RETURN gchar*
1209 g_intern_static_string (const gchar *string)
1211 GQuark quark;
1212 const gchar *result;
1214 if (!string)
1215 return NULL;
1217 G_LOCK (g_quark_global);
1218 quark = g_quark_from_string_internal (string, FALSE);
1219 result = g_quarks[quark];
1220 G_UNLOCK (g_quark_global);
1222 return result;