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()
40 #include "gdatasetprivate.h"
43 #include "gstrfuncs.h"
44 #include "gtestutils.h"
46 #include "glib_trace.h"
51 * @short_description: associate groups of data elements with
52 * particular memory locations
54 * Datasets associate groups of data elements with particular memory
55 * locations. These are useful if you need to associate data with a
56 * structure returned from an external library. Since you cannot modify
57 * the structure, you use its location in memory as the key into a
58 * dataset, where you can associate any number of data elements with it.
60 * There are two forms of most of the dataset functions. The first form
61 * uses strings to identify the data elements associated with a
62 * location. The second form uses #GQuark identifiers, which are
63 * created with a call to g_quark_from_string() or
64 * g_quark_from_static_string(). The second form is quicker, since it
65 * does not require looking up the string in the hash table of #GQuark
68 * There is no function to create a dataset. It is automatically
69 * created as soon as you add elements to it.
71 * To add data elements to a dataset use g_dataset_id_set_data(),
72 * g_dataset_id_set_data_full(), g_dataset_set_data() and
73 * g_dataset_set_data_full().
75 * To get data elements from a dataset use g_dataset_id_get_data() and
76 * g_dataset_get_data().
78 * To iterate over all data elements in a dataset use
79 * g_dataset_foreach() (not thread-safe).
81 * To remove data elements from a dataset use
82 * g_dataset_id_remove_data() and g_dataset_remove_data().
84 * To destroy a dataset, use g_dataset_destroy().
89 * @title: Keyed Data Lists
90 * @short_description: lists of data elements which are accessible by a
91 * string or GQuark identifier
93 * Keyed data lists provide lists of arbitrary data elements which can
94 * be accessed either with a string or with a #GQuark corresponding to
97 * The #GQuark methods are quicker, since the strings have to be
98 * converted to #GQuarks anyway.
100 * Data lists are used for associating arbitrary data with #GObjects,
101 * using g_object_set_data() and related functions.
103 * To create a datalist, use g_datalist_init().
105 * To add data elements to a datalist use g_datalist_id_set_data(),
106 * g_datalist_id_set_data_full(), g_datalist_set_data() and
107 * g_datalist_set_data_full().
109 * To get data elements from a datalist use g_datalist_id_get_data()
110 * and g_datalist_get_data().
112 * To iterate over all data elements in a datalist use
113 * g_datalist_foreach() (not thread-safe).
115 * To remove data elements from a datalist use
116 * g_datalist_id_remove_data() and g_datalist_remove_data().
118 * To remove all data elements from a datalist, use g_datalist_clear().
124 * The #GData struct is an opaque data structure to represent a <link
125 * linkend="glib-Keyed-Data-Lists">Keyed Data List</link>. It should
126 * only be accessed via the following functions.
131 * @data: the data element.
133 * Specifies the type of function which is called when a data element
134 * is destroyed. It is passed the pointer to the data element and
135 * should free any memory and resources allocated for it.
138 /* --- defines --- */
139 #define G_QUARK_BLOCK_SIZE (512)
141 #define G_DATALIST_FLAGS_MASK_INTERNAL 0x7
143 /* datalist pointer accesses have to be carried out atomically */
144 #define G_DATALIST_GET_POINTER(datalist) \
145 ((GData*) ((gsize) g_atomic_pointer_get (datalist) & ~(gsize) G_DATALIST_FLAGS_MASK_INTERNAL))
147 #define G_DATALIST_SET_POINTER(datalist, pointer) G_STMT_START { \
148 gpointer _oldv, _newv; \
150 _oldv = g_atomic_pointer_get (datalist); \
151 _newv = (gpointer) (((gsize) _oldv & G_DATALIST_FLAGS_MASK_INTERNAL) | (gsize) pointer); \
152 } while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, _oldv, _newv)); \
155 /* --- structures --- */
159 GDestroyNotify destroy;
162 typedef struct _GDataset GDataset;
165 guint32 len; /* Number of elements */
166 guint32 alloc; /* Number of allocated elements */
167 GDataElt data[1]; /* Flexible array */
172 gconstpointer location;
177 /* --- prototypes --- */
178 static inline GDataset* g_dataset_lookup (gconstpointer dataset_location);
179 static inline void g_datalist_clear_i (GData **datalist,
180 gboolean unlock_dataset);
181 static void g_dataset_destroy_internal (GDataset *dataset);
182 static inline gpointer g_data_set_internal (GData **datalist,
185 GDestroyNotify destroy_func,
187 static void g_data_initialize (void);
188 static inline GQuark g_quark_new (gchar *string);
192 * Each standalone GDataList is protected by a bitlock in the datalist pointer,
193 * which protects that modification of the non-flags part of the datalist pointer
194 * and the contents of the datalist.
196 * For GDataSet we have a global lock g_dataset_global that protects
197 * the global dataset hash and cache, and additionally it protects the
198 * datalist such that we can avoid to use the bit lock in a few places
202 /* --- variables --- */
203 G_LOCK_DEFINE_STATIC (g_dataset_global);
204 static GHashTable *g_dataset_location_ht = NULL;
205 static GDataset *g_dataset_cached = NULL; /* should this be
207 G_LOCK_DEFINE_STATIC (g_quark_global);
208 static GHashTable *g_quark_ht = NULL;
209 static gchar **g_quarks = NULL;
210 static GQuark g_quark_seq_id = 0;
212 /* --- functions --- */
214 #define DATALIST_LOCK_BIT 2
217 g_datalist_lock (GData **datalist)
219 g_pointer_bit_lock ((void **)datalist, DATALIST_LOCK_BIT);
223 g_datalist_unlock (GData **datalist)
225 g_pointer_bit_unlock ((void **)datalist, DATALIST_LOCK_BIT);
228 /* Called with the datalist lock held, or the dataset global
229 * lock for dataset lists
232 g_datalist_clear_i (GData **datalist, gboolean unlock_dataset)
237 data = G_DATALIST_GET_POINTER (datalist);
238 G_DATALIST_SET_POINTER (datalist, NULL);
243 G_UNLOCK (g_dataset_global);
244 for (i = 0; i < data->len; i++)
246 if (data->data[i].data && data->data[i].destroy)
247 data->data[i].destroy (data->data[i].data);
250 G_LOCK (g_dataset_global);
259 * @datalist: a datalist.
261 * Frees all the data elements of the datalist. The data elements'
262 * destroy functions are called if they have been set.
265 g_datalist_clear (GData **datalist)
267 g_return_if_fail (datalist != NULL);
269 g_datalist_lock (datalist);
271 g_datalist_clear_i (datalist, FALSE);
273 g_datalist_unlock (datalist);
276 /* HOLDS: g_dataset_global_lock */
277 static inline GDataset*
278 g_dataset_lookup (gconstpointer dataset_location)
280 register GDataset *dataset;
282 if (g_dataset_cached && g_dataset_cached->location == dataset_location)
283 return g_dataset_cached;
285 dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
287 g_dataset_cached = dataset;
292 /* HOLDS: g_dataset_global_lock */
294 g_dataset_destroy_internal (GDataset *dataset)
296 register gconstpointer dataset_location;
298 dataset_location = dataset->location;
301 if (G_DATALIST_GET_POINTER(&dataset->datalist) == NULL)
303 if (dataset == g_dataset_cached)
304 g_dataset_cached = NULL;
305 g_hash_table_remove (g_dataset_location_ht, dataset_location);
306 g_slice_free (GDataset, dataset);
310 g_datalist_clear_i (&dataset->datalist, TRUE);
311 dataset = g_dataset_lookup (dataset_location);
317 * @dataset_location: the location identifying the dataset.
319 * Destroys the dataset, freeing all memory allocated, and calling any
320 * destroy functions set for data elements.
323 g_dataset_destroy (gconstpointer dataset_location)
325 g_return_if_fail (dataset_location != NULL);
327 G_LOCK (g_dataset_global);
328 if (g_dataset_location_ht)
330 register GDataset *dataset;
332 dataset = g_dataset_lookup (dataset_location);
334 g_dataset_destroy_internal (dataset);
336 G_UNLOCK (g_dataset_global);
339 /* HOLDS: g_dataset_global_lock if dataset != null */
340 static inline gpointer
341 g_data_set_internal (GData **datalist,
344 GDestroyNotify new_destroy_func,
348 GDataElt old, *data, *data_last, *data_end;
350 g_datalist_lock (datalist);
352 d = G_DATALIST_GET_POINTER (datalist);
354 if (new_data == NULL) /* remove */
359 data_last = data + d->len - 1;
360 while (data <= data_last)
362 if (data->key == key_id)
365 if (data != data_last)
369 /* We don't bother to shrink, but if all data are now gone
370 * we at least free the memory
374 G_DATALIST_SET_POINTER (datalist, NULL);
377 /* the dataset destruction *must* be done
378 * prior to invocation of the data destroy function
381 g_dataset_destroy_internal (dataset);
384 g_datalist_unlock (datalist);
386 /* We found and removed an old value
387 * the GData struct *must* already be unlinked
388 * when invoking the destroy function.
389 * we use (new_data==NULL && new_destroy_func!=NULL) as
390 * a special hint combination to "steal"
391 * data without destroy notification
393 if (old.destroy && !new_destroy_func)
396 G_UNLOCK (g_dataset_global);
397 old.destroy (old.data);
399 G_LOCK (g_dataset_global);
415 data_end = data + d->len;
416 while (data < data_end)
418 if (data->key == key_id)
422 data->data = new_data;
423 data->destroy = new_destroy_func;
424 g_datalist_unlock (datalist);
429 data->data = new_data;
430 data->destroy = new_destroy_func;
432 g_datalist_unlock (datalist);
434 /* We found and replaced an old value
435 * the GData struct *must* already be unlinked
436 * when invoking the destroy function.
439 G_UNLOCK (g_dataset_global);
440 old.destroy (old.data);
442 G_LOCK (g_dataset_global);
450 /* The key was not found, insert it */
454 d = g_malloc (sizeof (GData));
458 else if (d->len == d->alloc)
460 d->alloc = d->alloc * 2;
461 d = g_realloc (d, sizeof (GData) + (d->alloc - 1) * sizeof (GDataElt));
464 G_DATALIST_SET_POINTER (datalist, d);
466 d->data[d->len].key = key_id;
467 d->data[d->len].data = new_data;
468 d->data[d->len].destroy = new_destroy_func;
472 g_datalist_unlock (datalist);
479 * g_dataset_id_set_data_full:
480 * @dataset_location: the location identifying the dataset.
481 * @key_id: the #GQuark id to identify the data element.
482 * @data: the data element.
483 * @destroy_func: the function to call when the data element is
484 * removed. This function will be called with the data
485 * element and can be used to free any memory allocated
488 * Sets the data element associated with the given #GQuark id, and also
489 * the function to call when the data element is destroyed. Any
490 * previous data with the same key is removed, and its destroy function
494 * g_dataset_set_data_full:
495 * @l: the location identifying the dataset.
496 * @k: the string to identify the data element.
497 * @d: the data element.
498 * @f: the function to call when the data element is removed. This
499 * function will be called with the data element and can be used to
500 * free any memory allocated for it.
502 * Sets the data corresponding to the given string identifier, and the
503 * function to call when the data element is destroyed.
506 * g_dataset_id_set_data:
507 * @l: the location identifying the dataset.
508 * @k: the #GQuark id to identify the data element.
509 * @d: the data element.
511 * Sets the data element associated with the given #GQuark id. Any
512 * previous data with the same key is removed, and its destroy function
516 * g_dataset_set_data:
517 * @l: the location identifying the dataset.
518 * @k: the string to identify the data element.
519 * @d: the data element.
521 * Sets the data corresponding to the given string identifier.
524 * g_dataset_id_remove_data:
525 * @l: the location identifying the dataset.
526 * @k: the #GQuark id identifying the data element.
528 * Removes a data element from a dataset. The data element's destroy
529 * function is called if it has been set.
532 * g_dataset_remove_data:
533 * @l: the location identifying the dataset.
534 * @k: the string identifying the data element.
536 * Removes a data element corresponding to a string. Its destroy
537 * function is called if it has been set.
540 g_dataset_id_set_data_full (gconstpointer dataset_location,
543 GDestroyNotify destroy_func)
545 register GDataset *dataset;
547 g_return_if_fail (dataset_location != NULL);
549 g_return_if_fail (destroy_func == NULL);
553 g_return_if_fail (key_id > 0);
558 G_LOCK (g_dataset_global);
559 if (!g_dataset_location_ht)
560 g_data_initialize ();
562 dataset = g_dataset_lookup (dataset_location);
565 dataset = g_slice_new (GDataset);
566 dataset->location = dataset_location;
567 g_datalist_init (&dataset->datalist);
568 g_hash_table_insert (g_dataset_location_ht,
569 (gpointer) dataset->location,
573 g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
574 G_UNLOCK (g_dataset_global);
578 * g_datalist_id_set_data_full:
579 * @datalist: a datalist.
580 * @key_id: the #GQuark to identify the data element.
581 * @data: the data element or %NULL to remove any previous element
582 * corresponding to @key_id.
583 * @destroy_func: the function to call when the data element is
584 * removed. This function will be called with the data
585 * element and can be used to free any memory allocated
586 * for it. If @data is %NULL, then @destroy_func must
589 * Sets the data corresponding to the given #GQuark id, and the
590 * function to be called when the element is removed from the datalist.
591 * Any previous data with the same key is removed, and its destroy
592 * function is called.
595 * g_datalist_set_data_full:
597 * @k: the string to identify the data element.
598 * @d: the data element, or %NULL to remove any previous element
599 * corresponding to @k.
600 * @f: the function to call when the data element is removed. This
601 * function will be called with the data element and can be used to
602 * free any memory allocated for it. If @d is %NULL, then @f must
605 * Sets the data element corresponding to the given string identifier,
606 * and the function to be called when the data element is removed.
609 * g_datalist_id_set_data:
611 * @q: the #GQuark to identify the data element.
612 * @d: the data element, or %NULL to remove any previous element
613 * corresponding to @q.
615 * Sets the data corresponding to the given #GQuark id. Any previous
616 * data with the same key is removed, and its destroy function is
620 * g_datalist_set_data:
622 * @k: the string to identify the data element.
623 * @d: the data element, or %NULL to remove any previous element
624 * corresponding to @k.
626 * Sets the data element corresponding to the given string identifier.
629 * g_datalist_id_remove_data:
631 * @q: the #GQuark identifying the data element.
633 * Removes an element, using its #GQuark identifier.
636 * g_datalist_remove_data:
638 * @k: the string identifying the data element.
640 * Removes an element using its string identifier. The data element's
641 * destroy function is called if it has been set.
644 g_datalist_id_set_data_full (GData **datalist,
647 GDestroyNotify destroy_func)
649 g_return_if_fail (datalist != NULL);
651 g_return_if_fail (destroy_func == NULL);
655 g_return_if_fail (key_id > 0);
660 g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
664 * g_dataset_id_remove_no_notify:
665 * @dataset_location: the location identifying the dataset.
666 * @key_id: the #GQuark ID identifying the data element.
667 * @Returns: the data previously stored at @key_id, or %NULL if none.
669 * Removes an element, without calling its destroy notification
673 * g_dataset_remove_no_notify:
674 * @l: the location identifying the dataset.
675 * @k: the string identifying the data element.
677 * Removes an element, without calling its destroy notifier.
680 g_dataset_id_remove_no_notify (gconstpointer dataset_location,
683 gpointer ret_data = NULL;
685 g_return_val_if_fail (dataset_location != NULL, NULL);
687 G_LOCK (g_dataset_global);
688 if (key_id && g_dataset_location_ht)
692 dataset = g_dataset_lookup (dataset_location);
694 ret_data = g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset);
696 G_UNLOCK (g_dataset_global);
702 * g_datalist_id_remove_no_notify:
703 * @datalist: a datalist.
704 * @key_id: the #GQuark identifying a data element.
705 * @Returns: the data previously stored at @key_id, or %NULL if none.
707 * Removes an element, without calling its destroy notification
711 * g_datalist_remove_no_notify:
713 * @k: the string identifying the data element.
715 * Removes an element, without calling its destroy notifier.
718 g_datalist_id_remove_no_notify (GData **datalist,
721 gpointer ret_data = NULL;
723 g_return_val_if_fail (datalist != NULL, NULL);
726 ret_data = g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
732 * g_dataset_id_get_data:
733 * @dataset_location: the location identifying the dataset.
734 * @key_id: the #GQuark id to identify the data element.
735 * @Returns: the data element corresponding to the #GQuark, or %NULL if
738 * Gets the data element corresponding to a #GQuark.
741 * g_dataset_get_data:
742 * @l: the location identifying the dataset.
743 * @k: the string identifying the data element.
744 * @Returns: the data element corresponding to the string, or %NULL if
747 * Gets the data element corresponding to a string.
750 g_dataset_id_get_data (gconstpointer dataset_location,
753 gpointer retval = NULL;
755 g_return_val_if_fail (dataset_location != NULL, NULL);
757 G_LOCK (g_dataset_global);
758 if (key_id && g_dataset_location_ht)
762 dataset = g_dataset_lookup (dataset_location);
764 retval = g_datalist_id_get_data (&dataset->datalist, key_id);
766 G_UNLOCK (g_dataset_global);
772 * g_datalist_id_get_data:
773 * @datalist: a datalist.
774 * @key_id: the #GQuark identifying a data element.
775 * @Returns: the data element, or %NULL if it is not found.
777 * Retrieves the data element corresponding to @key_id.
780 * g_datalist_get_data:
782 * @k: the string identifying a data element.
783 * @Returns: the data element, or %NULL if it is not found.
785 * Gets a data element, using its string identifer. This is slower than
786 * g_datalist_id_get_data() because the string is first converted to a
790 g_datalist_id_get_data (GData **datalist,
795 g_return_val_if_fail (datalist != NULL, NULL);
799 GDataElt *data, *data_end;
801 g_datalist_lock (datalist);
803 d = G_DATALIST_GET_POINTER (datalist);
807 data_end = data + d->len;
808 while (data < data_end)
810 if (data->key == key_id)
819 g_datalist_unlock (datalist);
827 * @key_id: the #GQuark id to identifying the data element.
828 * @data: the data element.
829 * @user_data: user data passed to g_dataset_foreach().
831 * Specifies the type of function passed to g_dataset_foreach(). It is
832 * called with each #GQuark id and associated data element, together
833 * with the @user_data parameter supplied to g_dataset_foreach().
838 * @dataset_location: the location identifying the dataset.
839 * @func: the function to call for each data element.
840 * @user_data: user data to pass to the function.
842 * Calls the given function for each data element which is associated
843 * with the given location. Note that this function is NOT thread-safe.
844 * So unless @datalist can be protected from any modifications during
845 * invocation of this function, it should not be called.
848 g_dataset_foreach (gconstpointer dataset_location,
849 GDataForeachFunc func,
852 register GDataset *dataset;
854 g_return_if_fail (dataset_location != NULL);
855 g_return_if_fail (func != NULL);
857 G_LOCK (g_dataset_global);
858 if (g_dataset_location_ht)
860 dataset = g_dataset_lookup (dataset_location);
861 G_UNLOCK (g_dataset_global);
863 g_datalist_foreach (&dataset->datalist, func, user_data);
867 G_UNLOCK (g_dataset_global);
872 * g_datalist_foreach:
873 * @datalist: a datalist.
874 * @func: the function to call for each data element.
875 * @user_data: user data to pass to the function.
877 * Calls the given function for each data element of the datalist. The
878 * function is called with each data element's #GQuark id and data,
879 * together with the given @user_data parameter. Note that this
880 * function is NOT thread-safe. So unless @datalist can be protected
881 * from any modifications during invocation of this function, it should
885 g_datalist_foreach (GData **datalist,
886 GDataForeachFunc func,
893 g_return_if_fail (datalist != NULL);
894 g_return_if_fail (func != NULL);
896 d = G_DATALIST_GET_POINTER (datalist);
900 /* We make a copy of the keys so that we can handle it changing
903 keys = g_new (GQuark, len);
904 for (i = 0; i < len; i++)
905 keys[i] = d->data[i].key;
907 for (i = 0; i < len; i++)
909 /* A previous callback might have removed a later item, so always check that
910 it still exists before calling */
911 d = G_DATALIST_GET_POINTER (datalist);
915 for (j = 0; j < d->len; j++)
917 if (d->data[j].key == keys[i]) {
918 func (d->data[i].key, d->data[i].data, user_data);
928 * @datalist: a pointer to a pointer to a datalist.
930 * Resets the datalist to %NULL. It does not free any memory or call
931 * any destroy functions.
934 g_datalist_init (GData **datalist)
936 g_return_if_fail (datalist != NULL);
938 g_atomic_pointer_set (datalist, NULL);
942 * g_datalist_set_flags:
943 * @datalist: pointer to the location that holds a list
944 * @flags: the flags to turn on. The values of the flags are
945 * restricted by %G_DATALIST_FLAGS_MASK (currently
946 * 3; giving two possible boolean flags).
947 * A value for @flags that doesn't fit within the mask is
950 * Turns on flag values for a data list. This function is used
951 * to keep a small number of boolean flags in an object with
952 * a data list without using any additional space. It is
953 * not generally useful except in circumstances where space
954 * is very tight. (It is used in the base #GObject type, for
960 g_datalist_set_flags (GData **datalist,
964 g_return_if_fail (datalist != NULL);
965 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
969 oldvalue = g_atomic_pointer_get (datalist);
971 while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
972 (gpointer) ((gsize) oldvalue | flags)));
976 * g_datalist_unset_flags:
977 * @datalist: pointer to the location that holds a list
978 * @flags: the flags to turn off. The values of the flags are
979 * restricted by %G_DATALIST_FLAGS_MASK (currently
980 * 3: giving two possible boolean flags).
981 * A value for @flags that doesn't fit within the mask is
984 * Turns off flag values for a data list. See g_datalist_unset_flags()
989 g_datalist_unset_flags (GData **datalist,
993 g_return_if_fail (datalist != NULL);
994 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
998 oldvalue = g_atomic_pointer_get (datalist);
1000 while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
1001 (gpointer) ((gsize) oldvalue & ~(gsize) flags)));
1005 * g_datalist_get_flags:
1006 * @datalist: pointer to the location that holds a list
1008 * Gets flags values packed in together with the datalist.
1009 * See g_datalist_set_flags().
1011 * Return value: the flags of the datalist
1016 g_datalist_get_flags (GData **datalist)
1018 g_return_val_if_fail (datalist != NULL, 0);
1020 return G_DATALIST_GET_FLAGS (datalist); /* atomic macro */
1023 /* HOLDS: g_dataset_global_lock */
1025 g_data_initialize (void)
1027 g_return_if_fail (g_dataset_location_ht == NULL);
1029 g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
1030 g_dataset_cached = NULL;
1036 * @short_description: a 2-way association between a string and a
1037 * unique integer identifier
1039 * Quarks are associations between strings and integer identifiers.
1040 * Given either the string or the #GQuark identifier it is possible to
1041 * retrieve the other.
1043 * Quarks are used for both <link
1044 * linkend="glib-datasets">Datasets</link> and <link
1045 * linkend="glib-keyed-data-lists">Keyed Data Lists</link>.
1047 * To create a new quark from a string, use g_quark_from_string() or
1048 * g_quark_from_static_string().
1050 * To find the string corresponding to a given #GQuark, use
1051 * g_quark_to_string().
1053 * To find the #GQuark corresponding to a given string, use
1054 * g_quark_try_string().
1056 * Another use for the string pool maintained for the quark functions
1057 * is string interning, using g_intern_string() or
1058 * g_intern_static_string(). An interned string is a canonical
1059 * representation for a string. One important advantage of interned
1060 * strings is that they can be compared for equality by a simple
1061 * pointer comparision, rather than using strcmp().
1067 * A GQuark is a non-zero integer which uniquely identifies a
1068 * particular string. A GQuark value of zero is associated to %NULL.
1072 * g_quark_try_string:
1073 * @string: a string.
1074 * @Returns: the #GQuark associated with the string, or 0 if @string is
1075 * %NULL or there is no #GQuark associated with it.
1077 * Gets the #GQuark associated with the given string, or 0 if string is
1078 * %NULL or it has no associated #GQuark.
1080 * If you want the GQuark to be created if it doesn't already exist,
1081 * use g_quark_from_string() or g_quark_from_static_string().
1084 g_quark_try_string (const gchar *string)
1091 G_LOCK (g_quark_global);
1093 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1094 G_UNLOCK (g_quark_global);
1099 #define QUARK_STRING_BLOCK_SIZE (4096 - sizeof (gsize))
1100 static char *quark_block = NULL;
1101 static int quark_block_offset = 0;
1103 /* HOLDS: g_quark_global_lock */
1105 quark_strdup(const gchar *string)
1110 len = strlen (string) + 1;
1112 /* For strings longer than half the block size, fall back
1113 to strdup so that we fill our blocks at least 50%. */
1114 if (len > QUARK_STRING_BLOCK_SIZE / 2)
1115 return g_strdup (string);
1117 if (quark_block == NULL ||
1118 QUARK_STRING_BLOCK_SIZE - quark_block_offset < len)
1120 quark_block = g_malloc (QUARK_STRING_BLOCK_SIZE);
1121 quark_block_offset = 0;
1124 copy = quark_block + quark_block_offset;
1125 memcpy (copy, string, len);
1126 quark_block_offset += len;
1131 /* HOLDS: g_quark_global_lock */
1132 static inline GQuark
1133 g_quark_from_string_internal (const gchar *string,
1139 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1143 quark = g_quark_new (duplicate ? quark_strdup (string) : (gchar *)string);
1144 TRACE(GLIB_QUARK_NEW(string, quark));
1151 * g_quark_from_string:
1152 * @string: a string.
1153 * @Returns: the #GQuark identifying the string, or 0 if @string is
1156 * Gets the #GQuark identifying the given string. If the string does
1157 * not currently have an associated #GQuark, a new #GQuark is created,
1158 * using a copy of the string.
1161 g_quark_from_string (const gchar *string)
1168 G_LOCK (g_quark_global);
1169 quark = g_quark_from_string_internal (string, TRUE);
1170 G_UNLOCK (g_quark_global);
1176 * g_quark_from_static_string:
1177 * @string: a string.
1178 * @Returns: the #GQuark identifying the string, or 0 if @string is
1181 * Gets the #GQuark identifying the given (static) string. If the
1182 * string does not currently have an associated #GQuark, a new #GQuark
1183 * is created, linked to the given string.
1185 * Note that this function is identical to g_quark_from_string() except
1186 * that if a new #GQuark is created the string itself is used rather
1187 * than a copy. This saves memory, but can only be used if the string
1188 * will <emphasis>always</emphasis> exist. It can be used with
1189 * statically allocated strings in the main program, but not with
1190 * statically allocated memory in dynamically loaded modules, if you
1191 * expect to ever unload the module again (e.g. do not use this
1192 * function in GTK+ theme engines).
1195 g_quark_from_static_string (const gchar *string)
1202 G_LOCK (g_quark_global);
1203 quark = g_quark_from_string_internal (string, FALSE);
1204 G_UNLOCK (g_quark_global);
1210 * g_quark_to_string:
1211 * @quark: a #GQuark.
1212 * @Returns: the string associated with the #GQuark.
1214 * Gets the string associated with the given #GQuark.
1216 G_CONST_RETURN gchar*
1217 g_quark_to_string (GQuark quark)
1219 gchar* result = NULL;
1221 G_LOCK (g_quark_global);
1222 if (quark < g_quark_seq_id)
1223 result = g_quarks[quark];
1224 G_UNLOCK (g_quark_global);
1229 /* HOLDS: g_quark_global_lock */
1230 static inline GQuark
1231 g_quark_new (gchar *string)
1235 if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
1236 g_quarks = g_renew (gchar*, g_quarks, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
1239 g_assert (g_quark_seq_id == 0);
1240 g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
1241 g_quarks[g_quark_seq_id++] = NULL;
1244 quark = g_quark_seq_id++;
1245 g_quarks[quark] = string;
1246 g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
1255 * Returns a canonical representation for @string. Interned strings can
1256 * be compared for equality by comparing the pointers, instead of using strcmp().
1258 * Returns: a canonical representation for the string
1262 G_CONST_RETURN gchar*
1263 g_intern_string (const gchar *string)
1265 const gchar *result;
1271 G_LOCK (g_quark_global);
1272 quark = g_quark_from_string_internal (string, TRUE);
1273 result = g_quarks[quark];
1274 G_UNLOCK (g_quark_global);
1280 * g_intern_static_string:
1281 * @string: a static string
1283 * Returns a canonical representation for @string. Interned strings can
1284 * be compared for equality by comparing the pointers, instead of using strcmp().
1285 * g_intern_static_string() does not copy the string, therefore @string must
1286 * not be freed or modified.
1288 * Returns: a canonical representation for the string
1292 G_CONST_RETURN gchar*
1293 g_intern_static_string (const gchar *string)
1296 const gchar *result;
1301 G_LOCK (g_quark_global);
1302 quark = g_quark_from_string_internal (string, FALSE);
1303 result = g_quarks[quark];
1304 G_UNLOCK (g_quark_global);