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()
38 #include "gdatasetprivate.h"
39 #include "glib_trace.h"
45 * @short_description: associate groups of data elements with
46 * particular memory locations
48 * Datasets associate groups of data elements with particular memory
49 * locations. These are useful if you need to associate data with a
50 * structure returned from an external library. Since you cannot modify
51 * the structure, you use its location in memory as the key into a
52 * dataset, where you can associate any number of data elements with it.
54 * There are two forms of most of the dataset functions. The first form
55 * uses strings to identify the data elements associated with a
56 * location. The second form uses #GQuark identifiers, which are
57 * created with a call to g_quark_from_string() or
58 * g_quark_from_static_string(). The second form is quicker, since it
59 * does not require looking up the string in the hash table of #GQuark
62 * There is no function to create a dataset. It is automatically
63 * created as soon as you add elements to it.
65 * To add data elements to a dataset use g_dataset_id_set_data(),
66 * g_dataset_id_set_data_full(), g_dataset_set_data() and
67 * g_dataset_set_data_full().
69 * To get data elements from a dataset use g_dataset_id_get_data() and
70 * g_dataset_get_data().
72 * To iterate over all data elements in a dataset use
73 * g_dataset_foreach() (not thread-safe).
75 * To remove data elements from a dataset use
76 * g_dataset_id_remove_data() and g_dataset_remove_data().
78 * To destroy a dataset, use g_dataset_destroy().
83 * @title: Keyed Data Lists
84 * @short_description: lists of data elements which are accessible by a
85 * string or GQuark identifier
87 * Keyed data lists provide lists of arbitrary data elements which can
88 * be accessed either with a string or with a #GQuark corresponding to
91 * The #GQuark methods are quicker, since the strings have to be
92 * converted to #GQuarks anyway.
94 * Data lists are used for associating arbitrary data with #GObjects,
95 * using g_object_set_data() and related functions.
97 * To create a datalist, use g_datalist_init().
99 * To add data elements to a datalist use g_datalist_id_set_data(),
100 * g_datalist_id_set_data_full(), g_datalist_set_data() and
101 * g_datalist_set_data_full().
103 * To get data elements from a datalist use g_datalist_id_get_data()
104 * and g_datalist_get_data().
106 * To iterate over all data elements in a datalist use
107 * g_datalist_foreach() (not thread-safe).
109 * To remove data elements from a datalist use
110 * g_datalist_id_remove_data() and g_datalist_remove_data().
112 * To remove all data elements from a datalist, use g_datalist_clear().
118 * The #GData struct is an opaque data structure to represent a <link
119 * linkend="glib-Keyed-Data-Lists">Keyed Data List</link>. It should
120 * only be accessed via the following functions.
125 * @data: the data element.
127 * Specifies the type of function which is called when a data element
128 * is destroyed. It is passed the pointer to the data element and
129 * should free any memory and resources allocated for it.
132 /* --- defines --- */
133 #define G_QUARK_BLOCK_SIZE (512)
135 /* datalist pointer accesses have to be carried out atomically */
136 #define G_DATALIST_GET_POINTER(datalist) \
137 ((GData*) ((gsize) g_atomic_pointer_get (datalist) & ~(gsize) G_DATALIST_FLAGS_MASK))
139 #define G_DATALIST_SET_POINTER(datalist, pointer) G_STMT_START { \
140 gpointer _oldv, _newv; \
142 _oldv = g_atomic_pointer_get (datalist); \
143 _newv = (gpointer) (((gsize) _oldv & G_DATALIST_FLAGS_MASK) | (gsize) pointer); \
144 } while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, _oldv, _newv)); \
147 /* --- structures --- */
148 typedef struct _GDataset GDataset;
154 GDestroyNotify destroy_func;
159 gconstpointer location;
164 /* --- prototypes --- */
165 static inline GDataset* g_dataset_lookup (gconstpointer dataset_location);
166 static inline void g_datalist_clear_i (GData **datalist);
167 static void g_dataset_destroy_internal (GDataset *dataset);
168 static inline gpointer g_data_set_internal (GData **datalist,
171 GDestroyNotify destroy_func,
173 static void g_data_initialize (void);
174 static inline GQuark g_quark_new (gchar *string);
177 /* --- variables --- */
178 G_LOCK_DEFINE_STATIC (g_dataset_global);
179 static GHashTable *g_dataset_location_ht = NULL;
180 static GDataset *g_dataset_cached = NULL; /* should this be
182 G_LOCK_DEFINE_STATIC (g_quark_global);
183 static GHashTable *g_quark_ht = NULL;
184 static gchar **g_quarks = NULL;
185 static GQuark g_quark_seq_id = 0;
187 /* --- functions --- */
189 /* HOLDS: g_dataset_global_lock */
191 g_datalist_clear_i (GData **datalist)
193 register GData *list;
195 /* unlink *all* items before walking their destructors
197 list = G_DATALIST_GET_POINTER (datalist);
198 G_DATALIST_SET_POINTER (datalist, NULL);
202 register GData *prev;
207 if (prev->destroy_func)
209 G_UNLOCK (g_dataset_global);
210 prev->destroy_func (prev->data);
211 G_LOCK (g_dataset_global);
214 g_slice_free (GData, prev);
220 * @datalist: a datalist.
222 * Frees all the data elements of the datalist. The data elements'
223 * destroy functions are called if they have been set.
226 g_datalist_clear (GData **datalist)
228 g_return_if_fail (datalist != NULL);
230 G_LOCK (g_dataset_global);
231 if (!g_dataset_location_ht)
232 g_data_initialize ();
234 while (G_DATALIST_GET_POINTER (datalist))
235 g_datalist_clear_i (datalist);
236 G_UNLOCK (g_dataset_global);
239 /* HOLDS: g_dataset_global_lock */
240 static inline GDataset*
241 g_dataset_lookup (gconstpointer dataset_location)
243 register GDataset *dataset;
245 if (g_dataset_cached && g_dataset_cached->location == dataset_location)
246 return g_dataset_cached;
248 dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
250 g_dataset_cached = dataset;
255 /* HOLDS: g_dataset_global_lock */
257 g_dataset_destroy_internal (GDataset *dataset)
259 register gconstpointer dataset_location;
261 dataset_location = dataset->location;
264 if (!dataset->datalist)
266 if (dataset == g_dataset_cached)
267 g_dataset_cached = NULL;
268 g_hash_table_remove (g_dataset_location_ht, dataset_location);
269 g_slice_free (GDataset, dataset);
273 g_datalist_clear_i (&dataset->datalist);
274 dataset = g_dataset_lookup (dataset_location);
280 * @dataset_location: the location identifying the dataset.
282 * Destroys the dataset, freeing all memory allocated, and calling any
283 * destroy functions set for data elements.
286 g_dataset_destroy (gconstpointer dataset_location)
288 g_return_if_fail (dataset_location != NULL);
290 G_LOCK (g_dataset_global);
291 if (g_dataset_location_ht)
293 register GDataset *dataset;
295 dataset = g_dataset_lookup (dataset_location);
297 g_dataset_destroy_internal (dataset);
299 G_UNLOCK (g_dataset_global);
302 /* HOLDS: g_dataset_global_lock */
303 static inline gpointer
304 g_data_set_internal (GData **datalist,
307 GDestroyNotify destroy_func,
310 register GData *list;
312 list = G_DATALIST_GET_POINTER (datalist);
315 register GData *prev;
320 if (list->id == key_id)
322 gpointer ret_data = NULL;
325 prev->next = list->next;
328 G_DATALIST_SET_POINTER (datalist, list->next);
330 /* the dataset destruction *must* be done
331 * prior to invocation of the data destroy function
333 if (!list->next && dataset)
334 g_dataset_destroy_internal (dataset);
337 /* the GData struct *must* already be unlinked
338 * when invoking the destroy function.
339 * we use (data==NULL && destroy_func!=NULL) as
340 * a special hint combination to "steal"
341 * data without destroy notification
343 if (list->destroy_func && !destroy_func)
345 G_UNLOCK (g_dataset_global);
346 list->destroy_func (list->data);
347 G_LOCK (g_dataset_global);
350 ret_data = list->data;
352 g_slice_free (GData, list);
365 if (list->id == key_id)
367 if (!list->destroy_func)
370 list->destroy_func = destroy_func;
374 register GDestroyNotify dfunc;
375 register gpointer ddata;
377 dfunc = list->destroy_func;
380 list->destroy_func = destroy_func;
382 /* we need to have updated all structures prior to
383 * invocation of the destroy function
385 G_UNLOCK (g_dataset_global);
387 G_LOCK (g_dataset_global);
396 list = g_slice_new (GData);
397 list->next = G_DATALIST_GET_POINTER (datalist);
400 list->destroy_func = destroy_func;
401 G_DATALIST_SET_POINTER (datalist, list);
408 * g_dataset_id_set_data_full:
409 * @dataset_location: the location identifying the dataset.
410 * @key_id: the #GQuark id to identify the data element.
411 * @data: the data element.
412 * @destroy_func: the function to call when the data element is
413 * removed. This function will be called with the data
414 * element and can be used to free any memory allocated
417 * Sets the data element associated with the given #GQuark id, and also
418 * the function to call when the data element is destroyed. Any
419 * previous data with the same key is removed, and its destroy function
423 * g_dataset_set_data_full:
424 * @l: the location identifying the dataset.
425 * @k: the string to identify the data element.
426 * @d: the data element.
427 * @f: the function to call when the data element is removed. This
428 * function will be called with the data element and can be used to
429 * free any memory allocated for it.
431 * Sets the data corresponding to the given string identifier, and the
432 * function to call when the data element is destroyed.
435 * g_dataset_id_set_data:
436 * @l: the location identifying the dataset.
437 * @k: the #GQuark id to identify the data element.
438 * @d: the data element.
440 * Sets the data element associated with the given #GQuark id. Any
441 * previous data with the same key is removed, and its destroy function
445 * g_dataset_set_data:
446 * @l: the location identifying the dataset.
447 * @k: the string to identify the data element.
448 * @d: the data element.
450 * Sets the data corresponding to the given string identifier.
453 * g_dataset_id_remove_data:
454 * @l: the location identifying the dataset.
455 * @k: the #GQuark id identifying the data element.
457 * Removes a data element from a dataset. The data element's destroy
458 * function is called if it has been set.
461 * g_dataset_remove_data:
462 * @l: the location identifying the dataset.
463 * @k: the string identifying the data element.
465 * Removes a data element corresponding to a string. Its destroy
466 * function is called if it has been set.
469 g_dataset_id_set_data_full (gconstpointer dataset_location,
472 GDestroyNotify destroy_func)
474 register GDataset *dataset;
476 g_return_if_fail (dataset_location != NULL);
478 g_return_if_fail (destroy_func == NULL);
482 g_return_if_fail (key_id > 0);
487 G_LOCK (g_dataset_global);
488 if (!g_dataset_location_ht)
489 g_data_initialize ();
491 dataset = g_dataset_lookup (dataset_location);
494 dataset = g_slice_new (GDataset);
495 dataset->location = dataset_location;
496 g_datalist_init (&dataset->datalist);
497 g_hash_table_insert (g_dataset_location_ht,
498 (gpointer) dataset->location,
502 g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
503 G_UNLOCK (g_dataset_global);
507 * g_datalist_id_set_data_full:
508 * @datalist: a datalist.
509 * @key_id: the #GQuark to identify the data element.
510 * @data: the data element or %NULL to remove any previous element
511 * corresponding to @key_id.
512 * @destroy_func: the function to call when the data element is
513 * removed. This function will be called with the data
514 * element and can be used to free any memory allocated
515 * for it. If @data is %NULL, then @destroy_func must
518 * Sets the data corresponding to the given #GQuark id, and the
519 * function to be called when the element is removed from the datalist.
520 * Any previous data with the same key is removed, and its destroy
521 * function is called.
524 * g_datalist_set_data_full:
526 * @k: the string to identify the data element.
527 * @d: the data element, or %NULL to remove any previous element
528 * corresponding to @k.
529 * @f: the function to call when the data element is removed. This
530 * function will be called with the data element and can be used to
531 * free any memory allocated for it. If @d is %NULL, then @f must
534 * Sets the data element corresponding to the given string identifier,
535 * and the function to be called when the data element is removed.
538 * g_datalist_id_set_data:
540 * @q: the #GQuark to identify the data element.
541 * @d: the data element, or %NULL to remove any previous element
542 * corresponding to @q.
544 * Sets the data corresponding to the given #GQuark id. Any previous
545 * data with the same key is removed, and its destroy function is
549 * g_datalist_set_data:
551 * @k: the string to identify the data element.
552 * @d: the data element, or %NULL to remove any previous element
553 * corresponding to @k.
555 * Sets the data element corresponding to the given string identifier.
558 * g_datalist_id_remove_data:
560 * @q: the #GQuark identifying the data element.
562 * Removes an element, using its #GQuark identifier.
565 * g_datalist_remove_data:
567 * @k: the string identifying the data element.
569 * Removes an element using its string identifier. The data element's
570 * destroy function is called if it has been set.
573 g_datalist_id_set_data_full (GData **datalist,
576 GDestroyNotify destroy_func)
578 g_return_if_fail (datalist != NULL);
580 g_return_if_fail (destroy_func == NULL);
584 g_return_if_fail (key_id > 0);
589 G_LOCK (g_dataset_global);
590 if (!g_dataset_location_ht)
591 g_data_initialize ();
593 g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
594 G_UNLOCK (g_dataset_global);
598 * g_dataset_id_remove_no_notify:
599 * @dataset_location: the location identifying the dataset.
600 * @key_id: the #GQuark ID identifying the data element.
601 * @Returns: the data previously stored at @key_id, or %NULL if none.
603 * Removes an element, without calling its destroy notification
607 * g_dataset_remove_no_notify:
608 * @l: the location identifying the dataset.
609 * @k: the string identifying the data element.
611 * Removes an element, without calling its destroy notifier.
614 g_dataset_id_remove_no_notify (gconstpointer dataset_location,
617 gpointer ret_data = NULL;
619 g_return_val_if_fail (dataset_location != NULL, NULL);
621 G_LOCK (g_dataset_global);
622 if (key_id && g_dataset_location_ht)
626 dataset = g_dataset_lookup (dataset_location);
628 ret_data = g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset);
630 G_UNLOCK (g_dataset_global);
636 * g_datalist_id_remove_no_notify:
637 * @datalist: a datalist.
638 * @key_id: the #GQuark identifying a data element.
639 * @Returns: the data previously stored at @key_id, or %NULL if none.
641 * Removes an element, without calling its destroy notification
645 * g_datalist_remove_no_notify:
647 * @k: the string identifying the data element.
649 * Removes an element, without calling its destroy notifier.
652 g_datalist_id_remove_no_notify (GData **datalist,
655 gpointer ret_data = NULL;
657 g_return_val_if_fail (datalist != NULL, NULL);
659 G_LOCK (g_dataset_global);
660 if (key_id && g_dataset_location_ht)
661 ret_data = g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
662 G_UNLOCK (g_dataset_global);
668 * g_dataset_id_get_data:
669 * @dataset_location: the location identifying the dataset.
670 * @key_id: the #GQuark id to identify the data element.
671 * @Returns: the data element corresponding to the #GQuark, or %NULL if
674 * Gets the data element corresponding to a #GQuark.
677 * g_dataset_get_data:
678 * @l: the location identifying the dataset.
679 * @k: the string identifying the data element.
680 * @Returns: the data element corresponding to the string, or %NULL if
683 * Gets the data element corresponding to a string.
686 g_dataset_id_get_data (gconstpointer dataset_location,
689 g_return_val_if_fail (dataset_location != NULL, NULL);
691 G_LOCK (g_dataset_global);
692 if (key_id && g_dataset_location_ht)
694 register GDataset *dataset;
696 dataset = g_dataset_lookup (dataset_location);
699 register GData *list;
701 for (list = dataset->datalist; list; list = list->next)
702 if (list->id == key_id)
704 G_UNLOCK (g_dataset_global);
709 G_UNLOCK (g_dataset_global);
715 * g_datalist_id_get_data:
716 * @datalist: a datalist.
717 * @key_id: the #GQuark identifying a data element.
718 * @Returns: the data element, or %NULL if it is not found.
720 * Retrieves the data element corresponding to @key_id.
723 * g_datalist_get_data:
725 * @k: the string identifying a data element.
726 * @Returns: the data element, or %NULL if it is not found.
728 * Gets a data element, using its string identifer. This is slower than
729 * g_datalist_id_get_data() because the string is first converted to a
733 g_datalist_id_get_data (GData **datalist,
736 gpointer data = NULL;
737 g_return_val_if_fail (datalist != NULL, NULL);
740 register GData *list;
741 G_LOCK (g_dataset_global);
742 for (list = G_DATALIST_GET_POINTER (datalist); list; list = list->next)
743 if (list->id == key_id)
748 G_UNLOCK (g_dataset_global);
755 * @key_id: the #GQuark id to identifying the data element.
756 * @data: the data element.
757 * @user_data: user data passed to g_dataset_foreach().
759 * Specifies the type of function passed to g_dataset_foreach(). It is
760 * called with each #GQuark id and associated data element, together
761 * with the @user_data parameter supplied to g_dataset_foreach().
766 * @dataset_location: the location identifying the dataset.
767 * @func: the function to call for each data element.
768 * @user_data: user data to pass to the function.
770 * Calls the given function for each data element which is associated
771 * with the given location. Note that this function is NOT thread-safe.
772 * So unless @datalist can be protected from any modifications during
773 * invocation of this function, it should not be called.
776 g_dataset_foreach (gconstpointer dataset_location,
777 GDataForeachFunc func,
780 register GDataset *dataset;
782 g_return_if_fail (dataset_location != NULL);
783 g_return_if_fail (func != NULL);
785 G_LOCK (g_dataset_global);
786 if (g_dataset_location_ht)
788 dataset = g_dataset_lookup (dataset_location);
789 G_UNLOCK (g_dataset_global);
792 register GData *list, *next;
794 for (list = dataset->datalist; list; list = next)
797 func (list->id, list->data, user_data);
803 G_UNLOCK (g_dataset_global);
808 * g_datalist_foreach:
809 * @datalist: a datalist.
810 * @func: the function to call for each data element.
811 * @user_data: user data to pass to the function.
813 * Calls the given function for each data element of the datalist. The
814 * function is called with each data element's #GQuark id and data,
815 * together with the given @user_data parameter. Note that this
816 * function is NOT thread-safe. So unless @datalist can be protected
817 * from any modifications during invocation of this function, it should
821 g_datalist_foreach (GData **datalist,
822 GDataForeachFunc func,
825 register GData *list, *next;
827 g_return_if_fail (datalist != NULL);
828 g_return_if_fail (func != NULL);
830 for (list = G_DATALIST_GET_POINTER (datalist); list; list = next)
833 func (list->id, list->data, user_data);
839 * @datalist: a pointer to a pointer to a datalist.
841 * Resets the datalist to %NULL. It does not free any memory or call
842 * any destroy functions.
845 g_datalist_init (GData **datalist)
847 g_return_if_fail (datalist != NULL);
849 g_atomic_pointer_set (datalist, NULL);
853 * g_datalist_set_flags:
854 * @datalist: pointer to the location that holds a list
855 * @flags: the flags to turn on. The values of the flags are
856 * restricted by %G_DATALIST_FLAGS_MASK (currently
857 * 3; giving two possible boolean flags).
858 * A value for @flags that doesn't fit within the mask is
861 * Turns on flag values for a data list. This function is used
862 * to keep a small number of boolean flags in an object with
863 * a data list without using any additional space. It is
864 * not generally useful except in circumstances where space
865 * is very tight. (It is used in the base #GObject type, for
871 g_datalist_set_flags (GData **datalist,
875 g_return_if_fail (datalist != NULL);
876 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
880 oldvalue = g_atomic_pointer_get (datalist);
882 while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
883 (gpointer) ((gsize) oldvalue | flags)));
887 * g_datalist_unset_flags:
888 * @datalist: pointer to the location that holds a list
889 * @flags: the flags to turn off. The values of the flags are
890 * restricted by %G_DATALIST_FLAGS_MASK (currently
891 * 3: giving two possible boolean flags).
892 * A value for @flags that doesn't fit within the mask is
895 * Turns off flag values for a data list. See g_datalist_unset_flags()
900 g_datalist_unset_flags (GData **datalist,
904 g_return_if_fail (datalist != NULL);
905 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
909 oldvalue = g_atomic_pointer_get (datalist);
911 while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
912 (gpointer) ((gsize) oldvalue & ~(gsize) flags)));
916 * g_datalist_get_flags:
917 * @datalist: pointer to the location that holds a list
919 * Gets flags values packed in together with the datalist.
920 * See g_datalist_set_flags().
922 * Return value: the flags of the datalist
927 g_datalist_get_flags (GData **datalist)
929 g_return_val_if_fail (datalist != NULL, 0);
931 return G_DATALIST_GET_FLAGS (datalist); /* atomic macro */
934 /* HOLDS: g_dataset_global_lock */
936 g_data_initialize (void)
938 g_return_if_fail (g_dataset_location_ht == NULL);
940 g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
941 g_dataset_cached = NULL;
947 * @short_description: a 2-way association between a string and a
948 * unique integer identifier
950 * Quarks are associations between strings and integer identifiers.
951 * Given either the string or the #GQuark identifier it is possible to
952 * retrieve the other.
954 * Quarks are used for both <link
955 * linkend="glib-datasets">Datasets</link> and <link
956 * linkend="glib-keyed-data-lists">Keyed Data Lists</link>.
958 * To create a new quark from a string, use g_quark_from_string() or
959 * g_quark_from_static_string().
961 * To find the string corresponding to a given #GQuark, use
962 * g_quark_to_string().
964 * To find the #GQuark corresponding to a given string, use
965 * g_quark_try_string().
967 * Another use for the string pool maintained for the quark functions
968 * is string interning, using g_intern_string() or
969 * g_intern_static_string(). An interned string is a canonical
970 * representation for a string. One important advantage of interned
971 * strings is that they can be compared for equality by a simple
972 * pointer comparision, rather than using strcmp().
978 * A GQuark is a non-zero integer which uniquely identifies a
979 * particular string. A GQuark value of zero is associated to %NULL.
983 * g_quark_try_string:
985 * @Returns: the #GQuark associated with the string, or 0 if @string is
986 * %NULL or there is no #GQuark associated with it.
988 * Gets the #GQuark associated with the given string, or 0 if string is
989 * %NULL or it has no associated #GQuark.
991 * If you want the GQuark to be created if it doesn't already exist,
992 * use g_quark_from_string() or g_quark_from_static_string().
995 g_quark_try_string (const gchar *string)
998 g_return_val_if_fail (string != NULL, 0);
1000 G_LOCK (g_quark_global);
1002 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1003 G_UNLOCK (g_quark_global);
1008 #define QUARK_STRING_BLOCK_SIZE (4096 - sizeof (gsize))
1009 static char *quark_block = NULL;
1010 static int quark_block_offset = 0;
1012 /* HOLDS: g_quark_global_lock */
1014 quark_strdup(const gchar *string)
1019 len = strlen (string) + 1;
1021 /* For strings longer than half the block size, fall back
1022 to strdup so that we fill our blocks at least 50%. */
1023 if (len > QUARK_STRING_BLOCK_SIZE / 2)
1024 return g_strdup (string);
1026 if (quark_block == NULL ||
1027 QUARK_STRING_BLOCK_SIZE - quark_block_offset < len)
1029 quark_block = g_malloc (QUARK_STRING_BLOCK_SIZE);
1030 quark_block_offset = 0;
1033 copy = quark_block + quark_block_offset;
1034 memcpy (copy, string, len);
1035 quark_block_offset += len;
1040 /* HOLDS: g_quark_global_lock */
1041 static inline GQuark
1042 g_quark_from_string_internal (const gchar *string,
1048 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1052 quark = g_quark_new (duplicate ? quark_strdup (string) : (gchar *)string);
1053 TRACE(GLIB_QUARK_NEW(string, quark));
1060 * g_quark_from_string:
1061 * @string: a string.
1062 * @Returns: the #GQuark identifying the string, or 0 if @string is
1065 * Gets the #GQuark identifying the given string. If the string does
1066 * not currently have an associated #GQuark, a new #GQuark is created,
1067 * using a copy of the string.
1070 g_quark_from_string (const gchar *string)
1077 G_LOCK (g_quark_global);
1078 quark = g_quark_from_string_internal (string, TRUE);
1079 G_UNLOCK (g_quark_global);
1085 * g_quark_from_static_string:
1086 * @string: a string.
1087 * @Returns: the #GQuark identifying the string, or 0 if @string is
1090 * Gets the #GQuark identifying the given (static) string. If the
1091 * string does not currently have an associated #GQuark, a new #GQuark
1092 * is created, linked to the given string.
1094 * Note that this function is identical to g_quark_from_string() except
1095 * that if a new #GQuark is created the string itself is used rather
1096 * than a copy. This saves memory, but can only be used if the string
1097 * will <emphasis>always</emphasis> exist. It can be used with
1098 * statically allocated strings in the main program, but not with
1099 * statically allocated memory in dynamically loaded modules, if you
1100 * expect to ever unload the module again (e.g. do not use this
1101 * function in GTK+ theme engines).
1104 g_quark_from_static_string (const gchar *string)
1111 G_LOCK (g_quark_global);
1112 quark = g_quark_from_string_internal (string, FALSE);
1113 G_UNLOCK (g_quark_global);
1119 * g_quark_to_string:
1120 * @quark: a #GQuark.
1121 * @Returns: the string associated with the #GQuark.
1123 * Gets the string associated with the given #GQuark.
1125 G_CONST_RETURN gchar*
1126 g_quark_to_string (GQuark quark)
1128 gchar* result = NULL;
1130 G_LOCK (g_quark_global);
1131 if (quark < g_quark_seq_id)
1132 result = g_quarks[quark];
1133 G_UNLOCK (g_quark_global);
1138 /* HOLDS: g_quark_global_lock */
1139 static inline GQuark
1140 g_quark_new (gchar *string)
1144 if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
1145 g_quarks = g_renew (gchar*, g_quarks, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
1148 g_assert (g_quark_seq_id == 0);
1149 g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
1150 g_quarks[g_quark_seq_id++] = NULL;
1153 quark = g_quark_seq_id++;
1154 g_quarks[quark] = string;
1155 g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
1164 * Returns a canonical representation for @string. Interned strings can
1165 * be compared for equality by comparing the pointers, instead of using strcmp().
1167 * Returns: a canonical representation for the string
1171 G_CONST_RETURN gchar*
1172 g_intern_string (const gchar *string)
1174 const gchar *result;
1180 G_LOCK (g_quark_global);
1181 quark = g_quark_from_string_internal (string, TRUE);
1182 result = g_quarks[quark];
1183 G_UNLOCK (g_quark_global);
1189 * g_intern_static_string:
1190 * @string: a static string
1192 * Returns a canonical representation for @string. Interned strings can
1193 * be compared for equality by comparing the pointers, instead of using strcmp().
1194 * g_intern_static_string() does not copy the string, therefore @string must
1195 * not be freed or modified.
1197 * Returns: a canonical representation for the string
1201 G_CONST_RETURN gchar*
1202 g_intern_static_string (const gchar *string)
1205 const gchar *result;
1210 G_LOCK (g_quark_global);
1211 quark = g_quark_from_string_internal (string, FALSE);
1212 result = g_quarks[quark];
1213 G_UNLOCK (g_quark_global);
1218 #define __G_DATASET_C__
1219 #include "galiasdef.c"