Skip to content
Newer
Older
100644 341 lines (307 sloc) 8.55 KB
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * lt-variant-db.c
4 * Copyright (C) 2011-2012 Akira TAGOH
5 *
6 * Authors:
7 * Akira TAGOH <akira@tagoh.org>
8 *
7eadc2a @tagoh Changed to the dual-licensing with MPLv2
authored Sep 21, 2012
9 * You may distribute under the terms of either the GNU
10 * Lesser General Public License or the Mozilla Public
11 * License, as specified in the README file.
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
12 */
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
17 #include <stdlib.h>
18 #include <string.h>
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
19 #include <libxml/xpath.h>
20 #include "lt-error.h"
d9ec445 @tagoh Add iterator support to lt_variant_db_t
authored Oct 29, 2012
21 #include "lt-iter-private.h"
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
22 #include "lt-variant.h"
23 #include "lt-variant-private.h"
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
24 #include "lt-list.h"
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
25 #include "lt-mem.h"
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
26 #include "lt-messages.h"
876c104 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
27 #include "lt-trie.h"
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
28 #include "lt-utils.h"
2b4a54c @tagoh Use common instance for xml files.
authored Jan 30, 2012
29 #include "lt-xml.h"
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
30 #include "lt-variant-db.h"
31
32
8afcdf2 @tagoh Update docs
authored Jan 18, 2012
33 /**
34 * SECTION: lt-variant-db
35 * @Short_Description: An interface to access Variant Database
36 * @Title: Database - Variant
37 *
38 * This class provides an interface to access Variant database. which has been
39 * registered with IANA.
40 */
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
41 struct _lt_variant_db_t {
d9ec445 @tagoh Add iterator support to lt_variant_db_t
authored Oct 29, 2012
42 lt_iter_tmpl_t parent;
43 lt_xml_t *xml;
44 lt_trie_t *variant_entries;
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
45 };
d9ec445 @tagoh Add iterator support to lt_variant_db_t
authored Oct 29, 2012
46 typedef struct _lt_variant_db_iter_t {
47 lt_iter_t parent;
48 lt_iter_t *iter;
49 } lt_variant_db_iter_t;
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
50
51 /*< private >*/
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
52 static lt_bool_t
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
53 lt_variant_db_parse(lt_variant_db_t *variantdb,
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
54 lt_error_t **error)
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
55 {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
56 lt_bool_t retval = TRUE;
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
57 xmlDocPtr doc = NULL;
58 xmlXPathContextPtr xctxt = NULL;
59 xmlXPathObjectPtr xobj = NULL;
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
60 lt_error_t *err = NULL;
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
61 int i, n;
62
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
63 lt_return_val_if_fail (variantdb != NULL, FALSE);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
64
2b4a54c @tagoh Use common instance for xml files.
authored Jan 30, 2012
65 doc = lt_xml_get_subtag_registry(variantdb->xml);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
66 xctxt = xmlXPathNewContext(doc);
67 if (!xctxt) {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
68 lt_error_set(&err, LT_ERR_OOM,
69 "Unable to create an instance of xmlXPathContextPtr.");
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
70 goto bail;
71 }
72 xobj = xmlXPathEvalExpression((const xmlChar *)"/registry/variant", xctxt);
73 if (!xobj) {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
74 lt_error_set(&err, LT_ERR_FAIL_ON_XML,
75 "No valid elements for %s",
76 doc->name);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
77 goto bail;
78 }
79 n = xmlXPathNodeSetGetLength(xobj->nodesetval);
80
81 for (i = 0; i < n; i++) {
82 xmlNodePtr ent = xmlXPathNodeSetItem(xobj->nodesetval, i);
83 xmlNodePtr cnode;
7139490 @tagoh update to deal with the missing fields
authored Jan 13, 2012
84 xmlChar *subtag = NULL, *desc = NULL, *preferred = NULL;
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
85 lt_variant_t *le = NULL;
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
86 char *s;
87 lt_list_t *prefix_list = NULL, *l;
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
88
89 if (!ent) {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
90 lt_error_set(&err, LT_ERR_FAIL_ON_XML,
91 "Unable to obtain the xml node via XPath.");
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
92 goto bail;
93 }
94 cnode = ent->children;
95 while (cnode != NULL) {
96 if (xmlStrcmp(cnode->name, (const xmlChar *)"subtag") == 0) {
7139490 @tagoh update to deal with the missing fields
authored Jan 13, 2012
97 if (subtag) {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
98 lt_warning("Duplicate subtag element in variant: previous value was '%s'",
99 subtag);
7139490 @tagoh update to deal with the missing fields
authored Jan 13, 2012
100 } else {
101 subtag = xmlNodeGetContent(cnode);
102 }
103 } else if (xmlStrcmp(cnode->name, (const xmlChar *)"added") == 0 ||
104 xmlStrcmp(cnode->name, (const xmlChar *)"text") == 0 ||
105 xmlStrcmp(cnode->name, (const xmlChar *)"comments") == 0 ||
106 xmlStrcmp(cnode->name, (const xmlChar *)"deprecated") == 0) {
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
107 /* ignore it */
108 } else if (xmlStrcmp(cnode->name, (const xmlChar *)"description") == 0) {
0a41d40 @tagoh Fix memory leaks
authored Jan 6, 2012
109 /* wonder if many descriptions helps something or is it a bug? */
198db3f @tagoh use the first entry for description
authored Jan 12, 2012
110 if (!desc)
111 desc = xmlNodeGetContent(cnode);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
112 } else if (xmlStrcmp(cnode->name, (const xmlChar *)"prefix") == 0) {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
113 prefix_list = lt_list_append(prefix_list,
114 xmlNodeGetContent(cnode),
115 (lt_destroy_func_t)xmlFree);
7139490 @tagoh update to deal with the missing fields
authored Jan 13, 2012
116 } else if (xmlStrcmp(cnode->name, (const xmlChar *)"preferred-value") == 0) {
117 if (preferred) {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
118 lt_warning("Duplicate preferred-value element in variant: previous value was '%s'",
119 preferred);
7139490 @tagoh update to deal with the missing fields
authored Jan 13, 2012
120 } else {
121 preferred = xmlNodeGetContent(cnode);
122 }
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
123 } else {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
124 lt_warning("Unknown node under /registry/variant: %s", cnode->name);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
125 }
126 cnode = cnode->next;
127 }
128 if (!subtag) {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
129 lt_warning("No subtag node: description = '%s', prefix = '%s', preferred-value = '%s'",
130 desc, prefix_list ? (char *)lt_list_value(prefix_list) : "N/A", preferred);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
131 goto bail1;
132 }
133 if (!desc) {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
134 lt_warning("No description node: subtag = '%s', prefix = '%s', preferred-value = '%s'",
135 subtag, prefix_list ? (char *)lt_list_value(prefix_list) : "N/A", preferred);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
136 goto bail1;
137 }
138 le = lt_variant_create();
139 if (!le) {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
140 lt_error_set(&err, LT_ERR_OOM,
141 "Unable to create an instance of lt_variant_t.");
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
142 goto bail1;
143 }
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
144 lt_variant_set_tag(le, (const char *)subtag);
145 lt_variant_set_name(le, (const char *)desc);
146 for (l = prefix_list; l != NULL; l = lt_list_next(l)) {
147 lt_variant_add_prefix(le, lt_list_value(l));
146fbd0 @tagoh Support multiple prefixes
authored Jan 11, 2012
148 }
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
149 lt_list_free(prefix_list);
7139490 @tagoh update to deal with the missing fields
authored Jan 13, 2012
150 if (preferred)
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
151 lt_variant_set_preferred_tag(le, (const char *)preferred);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
152
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
153 s = strdup(lt_variant_get_tag(le));
876c104 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
154 lt_trie_replace(variantdb->variant_entries,
155 lt_strlower(s),
156 lt_variant_ref(le),
157 (lt_destroy_func_t)lt_variant_unref);
158 free(s);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
159 bail1:
160 if (subtag)
161 xmlFree(subtag);
162 if (desc)
163 xmlFree(desc);
7139490 @tagoh update to deal with the missing fields
authored Jan 13, 2012
164 if (preferred)
165 xmlFree(preferred);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
166 lt_variant_unref(le);
167 }
168 bail:
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
169 if (lt_error_is_set(err, LT_ERR_ANY)) {
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
170 if (error)
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
171 *error = lt_error_ref(err);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
172 else
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
173 lt_error_print(err, LT_ERR_ANY);
174 lt_error_unref(err);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
175 retval = FALSE;
176 }
177
178 if (xobj)
179 xmlXPathFreeObject(xobj);
180 if (xctxt)
181 xmlXPathFreeContext(xctxt);
182
183 return retval;
184 }
185
d9ec445 @tagoh Add iterator support to lt_variant_db_t
authored Oct 29, 2012
186 static lt_iter_t *
187 _lt_variant_db_iter_init(lt_iter_tmpl_t *tmpl)
188 {
189 lt_variant_db_iter_t *retval;
190 lt_variant_db_t *db = (lt_variant_db_t *)tmpl;
191
192 retval = malloc(sizeof (lt_variant_db_iter_t));
193 if (retval) {
194 retval->iter = lt_iter_init((lt_iter_tmpl_t *)db->variant_entries);
195 if (!retval->iter) {
196 free(retval);
197 retval = NULL;
198 }
199 }
200
201 return &retval->parent;
202 }
203
204 static void
205 _lt_variant_db_iter_fini(lt_iter_t *iter)
206 {
207 lt_variant_db_iter_t *db_iter = (lt_variant_db_iter_t *)iter;
208
209 lt_iter_finish(db_iter->iter);
210 }
211
212 static lt_bool_t
213 _lt_variant_db_iter_next(lt_iter_t *iter,
214 lt_pointer_t *key,
215 lt_pointer_t *val)
216 {
217 lt_variant_db_iter_t *db_iter = (lt_variant_db_iter_t *)iter;
218
219 return lt_iter_next(db_iter->iter, key, val);
220 }
221
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
222 /*< public >*/
8afcdf2 @tagoh Update docs
authored Jan 18, 2012
223 /**
224 * lt_variant_db_new:
225 *
226 * Create a new instance of a #lt_variant_db_t.
227 *
228 * Returns: (transfer full): a new instance of #lt_variant_db_t.
229 */
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
230 lt_variant_db_t *
231 lt_variant_db_new(void)
232 {
233 lt_variant_db_t *retval = lt_mem_alloc_object(sizeof (lt_variant_db_t));
234
235 if (retval) {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
236 lt_error_t *err = NULL;
fce9380 @tagoh Add a wildcard entry and an empty entry for easier matching
authored Jan 13, 2012
237 lt_variant_t *le;
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
238
d9ec445 @tagoh Add iterator support to lt_variant_db_t
authored Oct 29, 2012
239 LT_ITER_TMPL_INIT (&retval->parent, _lt_variant_db);
240
876c104 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
241 retval->variant_entries = lt_trie_new();
d9ec445 @tagoh Add iterator support to lt_variant_db_t
authored Oct 29, 2012
242 lt_mem_add_ref((lt_mem_t *)retval, retval->variant_entries,
876c104 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
243 (lt_destroy_func_t)lt_trie_unref);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
244
fce9380 @tagoh Add a wildcard entry and an empty entry for easier matching
authored Jan 13, 2012
245 le = lt_variant_create();
246 lt_variant_set_tag(le, "*");
247 lt_variant_set_name(le, "Wildcard entry");
876c104 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
248 lt_trie_replace(retval->variant_entries,
249 lt_variant_get_tag(le),
250 le,
251 (lt_destroy_func_t)lt_variant_unref);
fce9380 @tagoh Add a wildcard entry and an empty entry for easier matching
authored Jan 13, 2012
252 le = lt_variant_create();
253 lt_variant_set_tag(le, "");
254 lt_variant_set_name(le, "Empty entry");
876c104 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
255 lt_trie_replace(retval->variant_entries,
256 lt_variant_get_tag(le),
257 le,
258 (lt_destroy_func_t)lt_variant_unref);
fce9380 @tagoh Add a wildcard entry and an empty entry for easier matching
authored Jan 13, 2012
259
2b4a54c @tagoh Use common instance for xml files.
authored Jan 30, 2012
260 retval->xml = lt_xml_new();
261 if (!retval->xml) {
262 lt_variant_db_unref(retval);
263 retval = NULL;
264 goto bail;
265 }
d9ec445 @tagoh Add iterator support to lt_variant_db_t
authored Oct 29, 2012
266 lt_mem_add_ref((lt_mem_t *)retval, retval->xml,
2b4a54c @tagoh Use common instance for xml files.
authored Jan 30, 2012
267 (lt_destroy_func_t)lt_xml_unref);
268
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
269 lt_variant_db_parse(retval, &err);
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
270 if (lt_error_is_set(err, LT_ERR_ANY)) {
271 lt_error_print(err, LT_ERR_ANY);
272 lt_error_unref(err);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
273 lt_variant_db_unref(retval);
274 retval = NULL;
275 }
276 }
2b4a54c @tagoh Use common instance for xml files.
authored Jan 30, 2012
277 bail:
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
278
279 return retval;
280 }
281
8afcdf2 @tagoh Update docs
authored Jan 18, 2012
282 /**
283 * lt_variant_db_ref:
284 * @variantdb: a #lt_variant_db_t.
285 *
286 * Increases the reference count of @variantdb.
287 *
288 * Returns: (transfer none): the same @variantdb object.
289 */
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
290 lt_variant_db_t *
291 lt_variant_db_ref(lt_variant_db_t *variantdb)
292 {
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
293 lt_return_val_if_fail (variantdb != NULL, NULL);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
294
d9ec445 @tagoh Add iterator support to lt_variant_db_t
authored Oct 29, 2012
295 return lt_mem_ref((lt_mem_t *)variantdb);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
296 }
297
8afcdf2 @tagoh Update docs
authored Jan 18, 2012
298 /**
299 * lt_variant_db_unref:
300 * @variantdb: a #lt_variant_db_t.
301 *
302 * Decreases the reference count of @variantdb. when its reference count
303 * drops to 0, the object is finalized (i.e. its memory is freed).
304 */
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
305 void
306 lt_variant_db_unref(lt_variant_db_t *variantdb)
307 {
308 if (variantdb)
d9ec445 @tagoh Add iterator support to lt_variant_db_t
authored Oct 29, 2012
309 lt_mem_unref((lt_mem_t *)variantdb);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
310 }
311
8afcdf2 @tagoh Update docs
authored Jan 18, 2012
312 /**
313 * lt_variant_db_lookup:
314 * @variantdb: a #lt_variant_db_t.
315 * @subtag: a subtag name to lookup.
316 *
317 * Lookup @lt_variant_t if @subtag is valid and registered into the database.
318 *
319 * Returns: (transfer full): a #lt_variant_t that meets with @subtag.
320 * otherwise %NULL.
321 */
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
322 lt_variant_t *
323 lt_variant_db_lookup(lt_variant_db_t *variantdb,
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
324 const char *subtag)
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
325 {
326 lt_variant_t *retval;
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
327 char *s;
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
328
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
329 lt_return_val_if_fail (variantdb != NULL, NULL);
330 lt_return_val_if_fail (subtag != NULL, NULL);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
331
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
332 s = strdup(subtag);
876c104 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
333 retval = lt_trie_lookup(variantdb->variant_entries,
334 lt_strlower(s));
0a1d171 @tagoh another try to clean up glib dependencies
authored Oct 5, 2012
335 free(s);
1af77b1 @tagoh Add variant database handler
authored Jan 6, 2012
336 if (retval)
337 return lt_variant_ref(retval);
338
339 return NULL;
340 }
Something went wrong with that request. Please try again.