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()
39 #include "gdatasetprivate.h"
42 #include "gtestutils.h"
44 #include "glib_trace.h"
49 * @short_description: associate groups of data elements with
50 * particular memory locations
52 * Datasets associate groups of data elements with particular memory
53 * locations. These are useful if you need to associate data with a
54 * structure returned from an external library. Since you cannot modify
55 * the structure, you use its location in memory as the key into a
56 * dataset, where you can associate any number of data elements with it.
58 * There are two forms of most of the dataset functions. The first form
59 * uses strings to identify the data elements associated with a
60 * location. The second form uses #GQuark identifiers, which are
61 * created with a call to g_quark_from_string() or
62 * g_quark_from_static_string(). The second form is quicker, since it
63 * does not require looking up the string in the hash table of #GQuark
66 * There is no function to create a dataset. It is automatically
67 * created as soon as you add elements to it.
69 * To add data elements to a dataset use g_dataset_id_set_data(),
70 * g_dataset_id_set_data_full(), g_dataset_set_data() and
71 * g_dataset_set_data_full().
73 * To get data elements from a dataset use g_dataset_id_get_data() and
74 * g_dataset_get_data().
76 * To iterate over all data elements in a dataset use
77 * g_dataset_foreach() (not thread-safe).
79 * To remove data elements from a dataset use
80 * g_dataset_id_remove_data() and g_dataset_remove_data().
82 * To destroy a dataset, use g_dataset_destroy().
87 * @title: Keyed Data Lists
88 * @short_description: lists of data elements which are accessible by a
89 * string or GQuark identifier
91 * Keyed data lists provide lists of arbitrary data elements which can
92 * be accessed either with a string or with a #GQuark corresponding to
95 * The #GQuark methods are quicker, since the strings have to be
96 * converted to #GQuarks anyway.
98 * Data lists are used for associating arbitrary data with #GObjects,
99 * using g_object_set_data() and related functions.
101 * To create a datalist, use g_datalist_init().
103 * To add data elements to a datalist use g_datalist_id_set_data(),
104 * g_datalist_id_set_data_full(), g_datalist_set_data() and
105 * g_datalist_set_data_full().
107 * To get data elements from a datalist use g_datalist_id_get_data()
108 * and g_datalist_get_data().
110 * To iterate over all data elements in a datalist use
111 * g_datalist_foreach() (not thread-safe).
113 * To remove data elements from a datalist use
114 * g_datalist_id_remove_data() and g_datalist_remove_data().
116 * To remove all data elements from a datalist, use g_datalist_clear().
122 * The #GData struct is an opaque data structure to represent a <link
123 * linkend="glib-Keyed-Data-Lists">Keyed Data List</link>. It should
124 * only be accessed via the following functions.
129 * @data: the data element.
131 * Specifies the type of function which is called when a data element
132 * is destroyed. It is passed the pointer to the data element and
133 * should free any memory and resources allocated for it.
136 /* --- defines --- */
137 #define G_QUARK_BLOCK_SIZE (512)
139 /* datalist pointer accesses have to be carried out atomically */
140 #define G_DATALIST_GET_POINTER(datalist) \
141 ((GData*) ((gsize) g_atomic_pointer_get (datalist) & ~(gsize) G_DATALIST_FLAGS_MASK))
143 #define G_DATALIST_SET_POINTER(datalist, pointer) G_STMT_START { \
144 gpointer _oldv, _newv; \
146 _oldv = g_atomic_pointer_get (datalist); \
147 _newv = (gpointer) (((gsize) _oldv & G_DATALIST_FLAGS_MASK) | (gsize) pointer); \
148 } while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, _oldv, _newv)); \
151 /* --- structures --- */
152 typedef struct _GDataset GDataset;
158 GDestroyNotify destroy_func;
163 gconstpointer location;
168 /* --- prototypes --- */
169 static inline GDataset* g_dataset_lookup (gconstpointer dataset_location);
170 static inline void g_datalist_clear_i (GData **datalist);
171 static void g_dataset_destroy_internal (GDataset *dataset);
172 static inline gpointer g_data_set_internal (GData **datalist,
175 GDestroyNotify destroy_func,
177 static void g_data_initialize (void);
178 static inline GQuark g_quark_new (gchar *string);
181 /* --- variables --- */
182 G_LOCK_DEFINE_STATIC (g_dataset_global);
183 static GHashTable *g_dataset_location_ht = NULL;
184 static GDataset *g_dataset_cached = NULL; /* should this be
186 G_LOCK_DEFINE_STATIC (g_quark_global);
187 static GHashTable *g_quark_ht = NULL;
188 static gchar **g_quarks = NULL;
189 static GQuark g_quark_seq_id = 0;
191 /* --- functions --- */
193 /* HOLDS: g_dataset_global_lock */
195 g_datalist_clear_i (GData **datalist)
197 register GData *list;
199 /* unlink *all* items before walking their destructors
201 list = G_DATALIST_GET_POINTER (datalist);
202 G_DATALIST_SET_POINTER (datalist, NULL);
206 register GData *prev;
211 if (prev->destroy_func)
213 G_UNLOCK (g_dataset_global);
214 prev->destroy_func (prev->data);
215 G_LOCK (g_dataset_global);
218 g_slice_free (GData, prev);
224 * @datalist: a datalist.
226 * Frees all the data elements of the datalist. The data elements'
227 * destroy functions are called if they have been set.
230 g_datalist_clear (GData **datalist)
232 g_return_if_fail (datalist != NULL);
234 G_LOCK (g_dataset_global);
235 if (!g_dataset_location_ht)
236 g_data_initialize ();
238 while (G_DATALIST_GET_POINTER (datalist))
239 g_datalist_clear_i (datalist);
240 G_UNLOCK (g_dataset_global);
243 /* HOLDS: g_dataset_global_lock */
244 static inline GDataset*
245 g_dataset_lookup (gconstpointer dataset_location)
247 register GDataset *dataset;
249 if (g_dataset_cached && g_dataset_cached->location == dataset_location)
250 return g_dataset_cached;
252 dataset = g_hash_table_lookup (g_dataset_location_ht, dataset_location);
254 g_dataset_cached = dataset;
259 /* HOLDS: g_dataset_global_lock */
261 g_dataset_destroy_internal (GDataset *dataset)
263 register gconstpointer dataset_location;
265 dataset_location = dataset->location;
268 if (!dataset->datalist)
270 if (dataset == g_dataset_cached)
271 g_dataset_cached = NULL;
272 g_hash_table_remove (g_dataset_location_ht, dataset_location);
273 g_slice_free (GDataset, dataset);
277 g_datalist_clear_i (&dataset->datalist);
278 dataset = g_dataset_lookup (dataset_location);
284 * @dataset_location: the location identifying the dataset.
286 * Destroys the dataset, freeing all memory allocated, and calling any
287 * destroy functions set for data elements.
290 g_dataset_destroy (gconstpointer dataset_location)
292 g_return_if_fail (dataset_location != NULL);
294 G_LOCK (g_dataset_global);
295 if (g_dataset_location_ht)
297 register GDataset *dataset;
299 dataset = g_dataset_lookup (dataset_location);
301 g_dataset_destroy_internal (dataset);
303 G_UNLOCK (g_dataset_global);
306 /* HOLDS: g_dataset_global_lock */
307 static inline gpointer
308 g_data_set_internal (GData **datalist,
311 GDestroyNotify destroy_func,
314 register GData *list;
316 list = G_DATALIST_GET_POINTER (datalist);
319 register GData *prev;
324 if (list->id == key_id)
326 gpointer ret_data = NULL;
329 prev->next = list->next;
332 G_DATALIST_SET_POINTER (datalist, list->next);
334 /* the dataset destruction *must* be done
335 * prior to invocation of the data destroy function
337 if (!list->next && dataset)
338 g_dataset_destroy_internal (dataset);
341 /* the GData struct *must* already be unlinked
342 * when invoking the destroy function.
343 * we use (data==NULL && destroy_func!=NULL) as
344 * a special hint combination to "steal"
345 * data without destroy notification
347 if (list->destroy_func && !destroy_func)
349 G_UNLOCK (g_dataset_global);
350 list->destroy_func (list->data);
351 G_LOCK (g_dataset_global);
354 ret_data = list->data;
356 g_slice_free (GData, list);
369 if (list->id == key_id)
371 if (!list->destroy_func)
374 list->destroy_func = destroy_func;
378 register GDestroyNotify dfunc;
379 register gpointer ddata;
381 dfunc = list->destroy_func;
384 list->destroy_func = destroy_func;
386 /* we need to have updated all structures prior to
387 * invocation of the destroy function
389 G_UNLOCK (g_dataset_global);
391 G_LOCK (g_dataset_global);
400 list = g_slice_new (GData);
401 list->next = G_DATALIST_GET_POINTER (datalist);
404 list->destroy_func = destroy_func;
405 G_DATALIST_SET_POINTER (datalist, list);
412 * g_dataset_id_set_data_full:
413 * @dataset_location: the location identifying the dataset.
414 * @key_id: the #GQuark id to identify the data element.
415 * @data: the data element.
416 * @destroy_func: the function to call when the data element is
417 * removed. This function will be called with the data
418 * element and can be used to free any memory allocated
421 * Sets the data element associated with the given #GQuark id, and also
422 * the function to call when the data element is destroyed. Any
423 * previous data with the same key is removed, and its destroy function
427 * g_dataset_set_data_full:
428 * @l: the location identifying the dataset.
429 * @k: the string to identify the data element.
430 * @d: the data element.
431 * @f: the function to call when the data element is removed. This
432 * function will be called with the data element and can be used to
433 * free any memory allocated for it.
435 * Sets the data corresponding to the given string identifier, and the
436 * function to call when the data element is destroyed.
439 * g_dataset_id_set_data:
440 * @l: the location identifying the dataset.
441 * @k: the #GQuark id to identify the data element.
442 * @d: the data element.
444 * Sets the data element associated with the given #GQuark id. Any
445 * previous data with the same key is removed, and its destroy function
449 * g_dataset_set_data:
450 * @l: the location identifying the dataset.
451 * @k: the string to identify the data element.
452 * @d: the data element.
454 * Sets the data corresponding to the given string identifier.
457 * g_dataset_id_remove_data:
458 * @l: the location identifying the dataset.
459 * @k: the #GQuark id identifying the data element.
461 * Removes a data element from a dataset. The data element's destroy
462 * function is called if it has been set.
465 * g_dataset_remove_data:
466 * @l: the location identifying the dataset.
467 * @k: the string identifying the data element.
469 * Removes a data element corresponding to a string. Its destroy
470 * function is called if it has been set.
473 g_dataset_id_set_data_full (gconstpointer dataset_location,
476 GDestroyNotify destroy_func)
478 register GDataset *dataset;
480 g_return_if_fail (dataset_location != NULL);
482 g_return_if_fail (destroy_func == NULL);
486 g_return_if_fail (key_id > 0);
491 G_LOCK (g_dataset_global);
492 if (!g_dataset_location_ht)
493 g_data_initialize ();
495 dataset = g_dataset_lookup (dataset_location);
498 dataset = g_slice_new (GDataset);
499 dataset->location = dataset_location;
500 g_datalist_init (&dataset->datalist);
501 g_hash_table_insert (g_dataset_location_ht,
502 (gpointer) dataset->location,
506 g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
507 G_UNLOCK (g_dataset_global);
511 * g_datalist_id_set_data_full:
512 * @datalist: a datalist.
513 * @key_id: the #GQuark to identify the data element.
514 * @data: the data element or %NULL to remove any previous element
515 * corresponding to @key_id.
516 * @destroy_func: the function to call when the data element is
517 * removed. This function will be called with the data
518 * element and can be used to free any memory allocated
519 * for it. If @data is %NULL, then @destroy_func must
522 * Sets the data corresponding to the given #GQuark id, and the
523 * function to be called when the element is removed from the datalist.
524 * Any previous data with the same key is removed, and its destroy
525 * function is called.
528 * g_datalist_set_data_full:
530 * @k: the string to identify the data element.
531 * @d: the data element, or %NULL to remove any previous element
532 * corresponding to @k.
533 * @f: the function to call when the data element is removed. This
534 * function will be called with the data element and can be used to
535 * free any memory allocated for it. If @d is %NULL, then @f must
538 * Sets the data element corresponding to the given string identifier,
539 * and the function to be called when the data element is removed.
542 * g_datalist_id_set_data:
544 * @q: the #GQuark to identify the data element.
545 * @d: the data element, or %NULL to remove any previous element
546 * corresponding to @q.
548 * Sets the data corresponding to the given #GQuark id. Any previous
549 * data with the same key is removed, and its destroy function is
553 * g_datalist_set_data:
555 * @k: the string to identify the data element.
556 * @d: the data element, or %NULL to remove any previous element
557 * corresponding to @k.
559 * Sets the data element corresponding to the given string identifier.
562 * g_datalist_id_remove_data:
564 * @q: the #GQuark identifying the data element.
566 * Removes an element, using its #GQuark identifier.
569 * g_datalist_remove_data:
571 * @k: the string identifying the data element.
573 * Removes an element using its string identifier. The data element's
574 * destroy function is called if it has been set.
577 g_datalist_id_set_data_full (GData **datalist,
580 GDestroyNotify destroy_func)
582 g_return_if_fail (datalist != NULL);
584 g_return_if_fail (destroy_func == NULL);
588 g_return_if_fail (key_id > 0);
593 G_LOCK (g_dataset_global);
594 if (!g_dataset_location_ht)
595 g_data_initialize ();
597 g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
598 G_UNLOCK (g_dataset_global);
602 * g_dataset_id_remove_no_notify:
603 * @dataset_location: the location identifying the dataset.
604 * @key_id: the #GQuark ID identifying the data element.
605 * @Returns: the data previously stored at @key_id, or %NULL if none.
607 * Removes an element, without calling its destroy notification
611 * g_dataset_remove_no_notify:
612 * @l: the location identifying the dataset.
613 * @k: the string identifying the data element.
615 * Removes an element, without calling its destroy notifier.
618 g_dataset_id_remove_no_notify (gconstpointer dataset_location,
621 gpointer ret_data = NULL;
623 g_return_val_if_fail (dataset_location != NULL, NULL);
625 G_LOCK (g_dataset_global);
626 if (key_id && g_dataset_location_ht)
630 dataset = g_dataset_lookup (dataset_location);
632 ret_data = g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset);
634 G_UNLOCK (g_dataset_global);
640 * g_datalist_id_remove_no_notify:
641 * @datalist: a datalist.
642 * @key_id: the #GQuark identifying a data element.
643 * @Returns: the data previously stored at @key_id, or %NULL if none.
645 * Removes an element, without calling its destroy notification
649 * g_datalist_remove_no_notify:
651 * @k: the string identifying the data element.
653 * Removes an element, without calling its destroy notifier.
656 g_datalist_id_remove_no_notify (GData **datalist,
659 gpointer ret_data = NULL;
661 g_return_val_if_fail (datalist != NULL, NULL);
663 G_LOCK (g_dataset_global);
664 if (key_id && g_dataset_location_ht)
665 ret_data = g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
666 G_UNLOCK (g_dataset_global);
672 * g_dataset_id_get_data:
673 * @dataset_location: the location identifying the dataset.
674 * @key_id: the #GQuark id to identify the data element.
675 * @Returns: the data element corresponding to the #GQuark, or %NULL if
678 * Gets the data element corresponding to a #GQuark.
681 * g_dataset_get_data:
682 * @l: the location identifying the dataset.
683 * @k: the string identifying the data element.
684 * @Returns: the data element corresponding to the string, or %NULL if
687 * Gets the data element corresponding to a string.
690 g_dataset_id_get_data (gconstpointer dataset_location,
693 g_return_val_if_fail (dataset_location != NULL, NULL);
695 G_LOCK (g_dataset_global);
696 if (key_id && g_dataset_location_ht)
698 register GDataset *dataset;
700 dataset = g_dataset_lookup (dataset_location);
703 register GData *list;
705 for (list = dataset->datalist; list; list = list->next)
706 if (list->id == key_id)
708 G_UNLOCK (g_dataset_global);
713 G_UNLOCK (g_dataset_global);
719 * g_datalist_id_get_data:
720 * @datalist: a datalist.
721 * @key_id: the #GQuark identifying a data element.
722 * @Returns: the data element, or %NULL if it is not found.
724 * Retrieves the data element corresponding to @key_id.
727 * g_datalist_get_data:
729 * @k: the string identifying a data element.
730 * @Returns: the data element, or %NULL if it is not found.
732 * Gets a data element, using its string identifer. This is slower than
733 * g_datalist_id_get_data() because the string is first converted to a
737 g_datalist_id_get_data (GData **datalist,
740 gpointer data = NULL;
741 g_return_val_if_fail (datalist != NULL, NULL);
744 register GData *list;
745 G_LOCK (g_dataset_global);
746 for (list = G_DATALIST_GET_POINTER (datalist); list; list = list->next)
747 if (list->id == key_id)
752 G_UNLOCK (g_dataset_global);
759 * @key_id: the #GQuark id to identifying the data element.
760 * @data: the data element.
761 * @user_data: user data passed to g_dataset_foreach().
763 * Specifies the type of function passed to g_dataset_foreach(). It is
764 * called with each #GQuark id and associated data element, together
765 * with the @user_data parameter supplied to g_dataset_foreach().
770 * @dataset_location: the location identifying the dataset.
771 * @func: the function to call for each data element.
772 * @user_data: user data to pass to the function.
774 * Calls the given function for each data element which is associated
775 * with the given location. Note that this function is NOT thread-safe.
776 * So unless @datalist can be protected from any modifications during
777 * invocation of this function, it should not be called.
780 g_dataset_foreach (gconstpointer dataset_location,
781 GDataForeachFunc func,
784 register GDataset *dataset;
786 g_return_if_fail (dataset_location != NULL);
787 g_return_if_fail (func != NULL);
789 G_LOCK (g_dataset_global);
790 if (g_dataset_location_ht)
792 dataset = g_dataset_lookup (dataset_location);
793 G_UNLOCK (g_dataset_global);
796 register GData *list, *next;
798 for (list = dataset->datalist; list; list = next)
801 func (list->id, list->data, user_data);
807 G_UNLOCK (g_dataset_global);
812 * g_datalist_foreach:
813 * @datalist: a datalist.
814 * @func: the function to call for each data element.
815 * @user_data: user data to pass to the function.
817 * Calls the given function for each data element of the datalist. The
818 * function is called with each data element's #GQuark id and data,
819 * together with the given @user_data parameter. Note that this
820 * function is NOT thread-safe. So unless @datalist can be protected
821 * from any modifications during invocation of this function, it should
825 g_datalist_foreach (GData **datalist,
826 GDataForeachFunc func,
829 register GData *list, *next;
831 g_return_if_fail (datalist != NULL);
832 g_return_if_fail (func != NULL);
834 for (list = G_DATALIST_GET_POINTER (datalist); list; list = next)
837 func (list->id, list->data, user_data);
843 * @datalist: a pointer to a pointer to a datalist.
845 * Resets the datalist to %NULL. It does not free any memory or call
846 * any destroy functions.
849 g_datalist_init (GData **datalist)
851 g_return_if_fail (datalist != NULL);
853 g_atomic_pointer_set (datalist, NULL);
857 * g_datalist_set_flags:
858 * @datalist: pointer to the location that holds a list
859 * @flags: the flags to turn on. The values of the flags are
860 * restricted by %G_DATALIST_FLAGS_MASK (currently
861 * 3; giving two possible boolean flags).
862 * A value for @flags that doesn't fit within the mask is
865 * Turns on flag values for a data list. This function is used
866 * to keep a small number of boolean flags in an object with
867 * a data list without using any additional space. It is
868 * not generally useful except in circumstances where space
869 * is very tight. (It is used in the base #GObject type, for
875 g_datalist_set_flags (GData **datalist,
879 g_return_if_fail (datalist != NULL);
880 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
884 oldvalue = g_atomic_pointer_get (datalist);
886 while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
887 (gpointer) ((gsize) oldvalue | flags)));
891 * g_datalist_unset_flags:
892 * @datalist: pointer to the location that holds a list
893 * @flags: the flags to turn off. The values of the flags are
894 * restricted by %G_DATALIST_FLAGS_MASK (currently
895 * 3: giving two possible boolean flags).
896 * A value for @flags that doesn't fit within the mask is
899 * Turns off flag values for a data list. See g_datalist_unset_flags()
904 g_datalist_unset_flags (GData **datalist,
908 g_return_if_fail (datalist != NULL);
909 g_return_if_fail ((flags & ~G_DATALIST_FLAGS_MASK) == 0);
913 oldvalue = g_atomic_pointer_get (datalist);
915 while (!g_atomic_pointer_compare_and_exchange ((void**) datalist, oldvalue,
916 (gpointer) ((gsize) oldvalue & ~(gsize) flags)));
920 * g_datalist_get_flags:
921 * @datalist: pointer to the location that holds a list
923 * Gets flags values packed in together with the datalist.
924 * See g_datalist_set_flags().
926 * Return value: the flags of the datalist
931 g_datalist_get_flags (GData **datalist)
933 g_return_val_if_fail (datalist != NULL, 0);
935 return G_DATALIST_GET_FLAGS (datalist); /* atomic macro */
938 /* HOLDS: g_dataset_global_lock */
940 g_data_initialize (void)
942 g_return_if_fail (g_dataset_location_ht == NULL);
944 g_dataset_location_ht = g_hash_table_new (g_direct_hash, NULL);
945 g_dataset_cached = NULL;
951 * @short_description: a 2-way association between a string and a
952 * unique integer identifier
954 * Quarks are associations between strings and integer identifiers.
955 * Given either the string or the #GQuark identifier it is possible to
956 * retrieve the other.
958 * Quarks are used for both <link
959 * linkend="glib-datasets">Datasets</link> and <link
960 * linkend="glib-keyed-data-lists">Keyed Data Lists</link>.
962 * To create a new quark from a string, use g_quark_from_string() or
963 * g_quark_from_static_string().
965 * To find the string corresponding to a given #GQuark, use
966 * g_quark_to_string().
968 * To find the #GQuark corresponding to a given string, use
969 * g_quark_try_string().
971 * Another use for the string pool maintained for the quark functions
972 * is string interning, using g_intern_string() or
973 * g_intern_static_string(). An interned string is a canonical
974 * representation for a string. One important advantage of interned
975 * strings is that they can be compared for equality by a simple
976 * pointer comparision, rather than using strcmp().
982 * A GQuark is a non-zero integer which uniquely identifies a
983 * particular string. A GQuark value of zero is associated to %NULL.
987 * g_quark_try_string:
989 * @Returns: the #GQuark associated with the string, or 0 if @string is
990 * %NULL or there is no #GQuark associated with it.
992 * Gets the #GQuark associated with the given string, or 0 if string is
993 * %NULL or it has no associated #GQuark.
995 * If you want the GQuark to be created if it doesn't already exist,
996 * use g_quark_from_string() or g_quark_from_static_string().
999 g_quark_try_string (const gchar *string)
1002 g_return_val_if_fail (string != NULL, 0);
1004 G_LOCK (g_quark_global);
1006 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1007 G_UNLOCK (g_quark_global);
1012 #define QUARK_STRING_BLOCK_SIZE (4096 - sizeof (gsize))
1013 static char *quark_block = NULL;
1014 static int quark_block_offset = 0;
1016 /* HOLDS: g_quark_global_lock */
1018 quark_strdup(const gchar *string)
1023 len = strlen (string) + 1;
1025 /* For strings longer than half the block size, fall back
1026 to strdup so that we fill our blocks at least 50%. */
1027 if (len > QUARK_STRING_BLOCK_SIZE / 2)
1028 return g_strdup (string);
1030 if (quark_block == NULL ||
1031 QUARK_STRING_BLOCK_SIZE - quark_block_offset < len)
1033 quark_block = g_malloc (QUARK_STRING_BLOCK_SIZE);
1034 quark_block_offset = 0;
1037 copy = quark_block + quark_block_offset;
1038 memcpy (copy, string, len);
1039 quark_block_offset += len;
1044 /* HOLDS: g_quark_global_lock */
1045 static inline GQuark
1046 g_quark_from_string_internal (const gchar *string,
1052 quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
1056 quark = g_quark_new (duplicate ? quark_strdup (string) : (gchar *)string);
1057 TRACE(GLIB_QUARK_NEW(string, quark));
1064 * g_quark_from_string:
1065 * @string: a string.
1066 * @Returns: the #GQuark identifying the string, or 0 if @string is
1069 * Gets the #GQuark identifying the given string. If the string does
1070 * not currently have an associated #GQuark, a new #GQuark is created,
1071 * using a copy of the string.
1074 g_quark_from_string (const gchar *string)
1081 G_LOCK (g_quark_global);
1082 quark = g_quark_from_string_internal (string, TRUE);
1083 G_UNLOCK (g_quark_global);
1089 * g_quark_from_static_string:
1090 * @string: a string.
1091 * @Returns: the #GQuark identifying the string, or 0 if @string is
1094 * Gets the #GQuark identifying the given (static) string. If the
1095 * string does not currently have an associated #GQuark, a new #GQuark
1096 * is created, linked to the given string.
1098 * Note that this function is identical to g_quark_from_string() except
1099 * that if a new #GQuark is created the string itself is used rather
1100 * than a copy. This saves memory, but can only be used if the string
1101 * will <emphasis>always</emphasis> exist. It can be used with
1102 * statically allocated strings in the main program, but not with
1103 * statically allocated memory in dynamically loaded modules, if you
1104 * expect to ever unload the module again (e.g. do not use this
1105 * function in GTK+ theme engines).
1108 g_quark_from_static_string (const gchar *string)
1115 G_LOCK (g_quark_global);
1116 quark = g_quark_from_string_internal (string, FALSE);
1117 G_UNLOCK (g_quark_global);
1123 * g_quark_to_string:
1124 * @quark: a #GQuark.
1125 * @Returns: the string associated with the #GQuark.
1127 * Gets the string associated with the given #GQuark.
1129 G_CONST_RETURN gchar*
1130 g_quark_to_string (GQuark quark)
1132 gchar* result = NULL;
1134 G_LOCK (g_quark_global);
1135 if (quark < g_quark_seq_id)
1136 result = g_quarks[quark];
1137 G_UNLOCK (g_quark_global);
1142 /* HOLDS: g_quark_global_lock */
1143 static inline GQuark
1144 g_quark_new (gchar *string)
1148 if (g_quark_seq_id % G_QUARK_BLOCK_SIZE == 0)
1149 g_quarks = g_renew (gchar*, g_quarks, g_quark_seq_id + G_QUARK_BLOCK_SIZE);
1152 g_assert (g_quark_seq_id == 0);
1153 g_quark_ht = g_hash_table_new (g_str_hash, g_str_equal);
1154 g_quarks[g_quark_seq_id++] = NULL;
1157 quark = g_quark_seq_id++;
1158 g_quarks[quark] = string;
1159 g_hash_table_insert (g_quark_ht, string, GUINT_TO_POINTER (quark));
1168 * Returns a canonical representation for @string. Interned strings can
1169 * be compared for equality by comparing the pointers, instead of using strcmp().
1171 * Returns: a canonical representation for the string
1175 G_CONST_RETURN gchar*
1176 g_intern_string (const gchar *string)
1178 const gchar *result;
1184 G_LOCK (g_quark_global);
1185 quark = g_quark_from_string_internal (string, TRUE);
1186 result = g_quarks[quark];
1187 G_UNLOCK (g_quark_global);
1193 * g_intern_static_string:
1194 * @string: a static string
1196 * Returns a canonical representation for @string. Interned strings can
1197 * be compared for equality by comparing the pointers, instead of using strcmp().
1198 * g_intern_static_string() does not copy the string, therefore @string must
1199 * not be freed or modified.
1201 * Returns: a canonical representation for the string
1205 G_CONST_RETURN gchar*
1206 g_intern_static_string (const gchar *string)
1209 const gchar *result;
1214 G_LOCK (g_quark_global);
1215 quark = g_quark_from_string_internal (string, FALSE);
1216 result = g_quarks[quark];
1217 G_UNLOCK (g_quark_global);