gio/ docs fixup
[platform/upstream/glib.git] / gio / gsettingsschema.c
1 /*
2  * Copyright © 2010 Codethink Limited
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the licence, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include "gsettingsschema.h"
23 #include "gvdb/gvdb-reader.h"
24
25 #include <glibintl.h>
26
27 G_DEFINE_TYPE (GSettingsSchema, g_settings_schema, G_TYPE_OBJECT)
28
29 struct _GSettingsSchemaPrivate
30 {
31   const gchar *gettext_domain;
32   const gchar *path;
33   GQuark *items;
34   gint n_items;
35   GvdbTable *table;
36   gchar *name;
37 };
38
39 static GSList *schema_sources;
40
41 static void
42 initialise_schema_sources (void)
43 {
44   static gsize initialised;
45
46   if G_UNLIKELY (g_once_init_enter (&initialised))
47     {
48       const gchar * const *dir;
49       const gchar *path;
50
51       for (dir = g_get_system_data_dirs (); *dir; dir++)
52         {
53           gchar *filename;
54           GvdbTable *table;
55
56           filename = g_build_filename (*dir, "glib-2.0", "schemas",
57                                        "gschemas.compiled", NULL);
58           table = gvdb_table_new (filename, TRUE, NULL);
59
60           if (table != NULL)
61             schema_sources = g_slist_prepend (schema_sources, table);
62
63           g_free (filename);
64         }
65
66       schema_sources = g_slist_reverse (schema_sources);
67
68       if ((path = g_getenv ("GSETTINGS_SCHEMA_DIR")) != NULL)
69         {
70           gchar *filename;
71           GvdbTable *table;
72
73           filename = g_build_filename (path, "gschemas.compiled", NULL);
74           table = gvdb_table_new (filename, TRUE, NULL);
75
76           if (table != NULL)
77             schema_sources = g_slist_prepend (schema_sources, table);
78
79           g_free (filename);
80         }
81
82       g_once_init_leave (&initialised, TRUE);
83     }
84 }
85
86 static void
87 add_item (gpointer key,
88           gpointer value,
89           gpointer user_data)
90 {
91   gchar ***ptr = user_data;
92
93   *(*ptr)++ = (gchar *) key;
94 }
95
96 /**
97  * g_settings_list_schemas:
98  * @returns: a list of the schemas installed on the system
99  *
100  * Returns a list of GSettings schemas that are available.  The list
101  * must not be modified or freed.
102  **/
103 const gchar * const *
104 g_settings_list_schemas (void)
105 {
106   static gsize schema_list;
107
108   if (g_once_init_enter (&schema_list))
109     {
110       GHashTable *builder;
111       GSList *source;
112       gchar **list;
113       gchar **ptr;
114       gint i;
115
116       initialise_schema_sources ();
117
118       builder = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
119
120       for (source = schema_sources; source; source = source->next)
121         {
122           list = gvdb_table_list (source->data, "");
123
124           if (list)
125             {
126               for (i = 0; list[i]; i++)
127                 g_hash_table_insert (builder, list[i], NULL);
128
129               /* not strfreev: we stole the strings into the hashtable */
130               g_free (list);
131             }
132         }
133
134       ptr = list = g_new (gchar *, g_hash_table_size (builder) + 1);
135       g_hash_table_foreach (builder, add_item, &ptr);
136       *ptr = NULL;
137
138       g_hash_table_steal_all (builder);
139       g_hash_table_unref (builder);
140
141       g_once_init_leave (&schema_list, (gsize) list);
142     }
143
144   return (const gchar **) schema_list;
145 }
146
147 static void
148 g_settings_schema_finalize (GObject *object)
149 {
150   GSettingsSchema *schema = G_SETTINGS_SCHEMA (object);
151
152   gvdb_table_unref (schema->priv->table);
153   g_free (schema->priv->items);
154   g_free (schema->priv->name);
155
156   G_OBJECT_CLASS (g_settings_schema_parent_class)
157     ->finalize (object);
158 }
159
160 static void
161 g_settings_schema_init (GSettingsSchema *schema)
162 {
163   schema->priv = G_TYPE_INSTANCE_GET_PRIVATE (schema, G_TYPE_SETTINGS_SCHEMA,
164                                               GSettingsSchemaPrivate);
165 }
166
167 static void
168 g_settings_schema_class_init (GSettingsSchemaClass *class)
169 {
170   GObjectClass *object_class = G_OBJECT_CLASS (class);
171
172   object_class->finalize = g_settings_schema_finalize;
173
174   g_type_class_add_private (class, sizeof (GSettingsSchemaPrivate));
175 }
176
177 const gchar *
178 g_settings_schema_get_string (GSettingsSchema *schema,
179                               const gchar     *key)
180 {
181   const gchar *result = NULL;
182   GVariant *value;
183
184   if ((value = gvdb_table_get_value (schema->priv->table, key)))
185     {
186       result = g_variant_get_string (value, NULL);
187       g_variant_unref (value);
188     }
189
190   return result;
191 }
192
193 GSettingsSchema *
194 g_settings_schema_new (const gchar *name)
195 {
196   GSettingsSchema *schema;
197   GvdbTable *table = NULL;
198   GSList *source;
199
200   initialise_schema_sources ();
201
202   for (source = schema_sources; source; source = source->next)
203     {
204       GvdbTable *file = source->data;
205
206       if ((table = gvdb_table_get_table (file, name)))
207         break;
208     }
209
210   if (table == NULL)
211     g_error ("Settings schema '%s' is not installed\n", name);
212
213   schema = g_object_new (G_TYPE_SETTINGS_SCHEMA, NULL);
214   schema->priv->name = g_strdup (name);
215   schema->priv->table = table;
216   schema->priv->path =
217     g_settings_schema_get_string (schema, ".path");
218   schema->priv->gettext_domain =
219     g_settings_schema_get_string (schema, ".gettext-domain");
220
221   if (schema->priv->gettext_domain)
222     bind_textdomain_codeset (schema->priv->gettext_domain, "UTF-8");
223
224   return schema;
225 }
226
227 GVariantIter *
228 g_settings_schema_get_value (GSettingsSchema *schema,
229                              const gchar     *key)
230 {
231   GVariantIter *iter;
232   GVariant *value;
233
234   value = gvdb_table_get_value (schema->priv->table, key);
235
236   if G_UNLIKELY (value == NULL)
237     g_error ("schema does not contain a key named '%s'", key);
238
239 #if G_BYTE_ORDER == G_BIG_ENDIAN
240   {
241     GVariant *tmp;
242
243     tmp = g_variant_byteswap (value);
244     g_variant_unref (value);
245     value = tmp;
246   }
247 #endif
248
249   iter = g_variant_iter_new (value);
250   g_variant_unref (value);
251
252   return iter;
253 }
254
255 const gchar *
256 g_settings_schema_get_path (GSettingsSchema *schema)
257 {
258   return schema->priv->path;
259 }
260
261 const gchar *
262 g_settings_schema_get_gettext_domain (GSettingsSchema *schema)
263 {
264   return schema->priv->gettext_domain;
265 }
266
267 gboolean
268 g_settings_schema_has_key (GSettingsSchema *schema,
269                            const gchar     *key)
270 {
271   return gvdb_table_has_value (schema->priv->table, key);
272 }
273
274 const GQuark *
275 g_settings_schema_list (GSettingsSchema *schema,
276                         gint            *n_items)
277 {
278   gint i, j;
279
280   if (schema->priv->items == NULL)
281     {
282       gchar **list;
283       gint len;
284
285       list = gvdb_table_list (schema->priv->table, "");
286       len = g_strv_length (list);
287
288       schema->priv->items = g_new (GQuark, len);
289       j = 0;
290
291       for (i = 0; i < len; i++)
292         if (list[i][0] != '.')
293           schema->priv->items[j++] = g_quark_from_string (list[i]);
294       schema->priv->n_items = j;
295
296       g_strfreev (list);
297     }
298
299   *n_items = schema->priv->n_items;
300   return schema->priv->items;
301 }