dont use obsolete xmlChildrenNode
[mikachu/openbox.git] / parser / parse.c
1 #include "parse.h"
2 #include <glib.h>
3
4 struct Callback {
5     char *tag;
6     ParseCallback func;
7     void *data;
8 };
9
10 struct _ObParseInst {
11     GHashTable *callbacks;
12 };
13
14 static void destfunc(struct Callback *c)
15 {
16     g_free(c->tag);
17     g_free(c);
18 }
19
20 ObParseInst* parse_startup()
21 {
22     ObParseInst *i = g_new(ObParseInst, 1);
23     i->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
24                                          (GDestroyNotify)destfunc);
25     return i;
26 }
27
28 void parse_shutdown(ObParseInst *i)
29 {
30     if (i) {
31         g_hash_table_destroy(i->callbacks);
32         g_free(i);
33     }
34 }
35
36 void parse_register(ObParseInst *i, const char *tag,
37                     ParseCallback func, void *data)
38 {
39     struct Callback *c;
40
41     if ((c = g_hash_table_lookup(i->callbacks, tag))) {
42         g_warning("tag '%s' already registered", tag);
43         return;
44     }
45
46     c = g_new(struct Callback, 1);
47     c->tag = g_strdup(tag);
48     c->func = func;
49     c->data = data;
50     g_hash_table_insert(i->callbacks, c->tag, c);
51 }
52
53 gboolean parse_load_rc(xmlDocPtr *doc, xmlNodePtr *root)
54 {
55     char *path;
56     gboolean r = FALSE;
57
58     path = g_build_filename(g_get_home_dir(), ".openbox", "rc.xml", NULL);
59     if (parse_load(path, "openbox_config", doc, root)) {
60         r = TRUE;
61     } else {
62         g_free(path);
63         path = g_build_filename(RCDIR, "rc.xml", NULL);
64         if (parse_load(path, "openbox_config", doc, root)) {
65             r = TRUE;
66         }
67     }
68     g_free(path);
69     if (!r)
70         g_warning("unable to find a valid config file, using defaults");
71     return r;
72 }
73
74 gboolean parse_load(const char *path, const char *rootname,
75                     xmlDocPtr *doc, xmlNodePtr *root)
76 {
77     if ((*doc = xmlParseFile(path))) {
78         *root = xmlDocGetRootElement(*doc);
79         if (!*root) {
80             xmlFreeDoc(*doc);
81             *doc = NULL;
82             g_warning("%s is an empty document", path);
83         } else {
84             if (xmlStrcasecmp((*root)->name, (const xmlChar*)rootname)) {
85                 xmlFreeDoc(*doc);
86                 *doc = NULL;
87                 g_warning("document %s is of wrong type. root node is "
88                           "not '%s'", path, rootname);
89             }
90         }
91     }
92     if (!*doc)
93         return FALSE;
94     return TRUE;
95 }
96
97 gboolean parse_load_mem(gpointer data, guint len, const char *rootname,
98                         xmlDocPtr *doc, xmlNodePtr *root)
99 {
100     if ((*doc = xmlParseMemory(data, len))) {
101         *root = xmlDocGetRootElement(*doc);
102         if (!*root) {
103             xmlFreeDoc(*doc);
104             *doc = NULL;
105             g_warning("Given memory is an empty document");
106         } else {
107             if (xmlStrcasecmp((*root)->name, (const xmlChar*)rootname)) {
108                 xmlFreeDoc(*doc);
109                 *doc = NULL;
110                 g_warning("document in given memory is of wrong type. root "
111                           "node is not '%s'", rootname);
112             }
113         }
114     }
115     if (!*doc)
116         return FALSE;
117     return TRUE;
118 }
119
120 void parse_close(xmlDocPtr doc)
121 {
122     xmlFree(doc);
123 }
124
125 void parse_tree(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
126 {
127     while (node) {
128         struct Callback *c = g_hash_table_lookup(i->callbacks, node->name);
129
130         if (c)
131             c->func(i, doc, node, c->data);
132
133         node = node->next;
134     }
135 }
136
137 char *parse_string(xmlDocPtr doc, xmlNodePtr node)
138 {
139     xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
140     char *s = g_strdup(c ? (char*)c : "");
141     xmlFree(c);
142     return s;
143 }
144
145 int parse_int(xmlDocPtr doc, xmlNodePtr node)
146 {
147     xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
148     int i = atoi((char*)c);
149     xmlFree(c);
150     return i;
151 }
152
153 gboolean parse_bool(xmlDocPtr doc, xmlNodePtr node)
154 {
155     xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
156     gboolean b = FALSE;
157     if (!xmlStrcasecmp(c, (const xmlChar*) "true"))
158         b = TRUE;
159     else if (!xmlStrcasecmp(c, (const xmlChar*) "yes"))
160         b = TRUE;
161     else if (!xmlStrcasecmp(c, (const xmlChar*) "on"))
162         b = TRUE;
163     xmlFree(c);
164     return b;
165 }
166
167 gboolean parse_contains(const char *val, xmlDocPtr doc, xmlNodePtr node)
168 {
169     xmlChar *c = xmlNodeListGetString(doc, node->children, TRUE);
170     gboolean r;
171     r = !xmlStrcasecmp(c, (const xmlChar*) val);
172     xmlFree(c);
173     return r;
174 }
175
176 xmlNodePtr parse_find_node(const char *tag, xmlNodePtr node)
177 {
178     while (node) {
179         if (!xmlStrcasecmp(node->name, (const xmlChar*) tag))
180             return node;
181         node = node->next;
182     }
183     return NULL;
184 }
185
186 gboolean parse_attr_int(const char *name, xmlNodePtr node, int *value)
187 {
188     xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
189     gboolean r = FALSE;
190     if (c) {
191         *value = atoi((char*)c);
192         r = TRUE;
193     }
194     xmlFree(c);
195     return r;
196 }
197
198 gboolean parse_attr_string(const char *name, xmlNodePtr node, char **value)
199 {
200     xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
201     gboolean r = FALSE;
202     if (c) {
203         *value = g_strdup((char*)c);
204         r = TRUE;
205     }
206     xmlFree(c);
207     return r;
208 }
209
210 gboolean parse_attr_contains(const char *val, xmlNodePtr node,
211                              const char *name)
212 {
213     xmlChar *c = xmlGetProp(node, (const xmlChar*) name);
214     gboolean r;
215     r = !xmlStrcasecmp(c, (const xmlChar*) val);
216     xmlFree(c);
217     return r;
218 }