~ubuntu-branches/ubuntu/hardy/irssi/hardy-updates

« back to all changes in this revision

Viewing changes to src/lib-config/get.c

  • Committer: Bazaar Package Importer
  • Author(s): David Pashley
  • Date: 2005-12-10 21:25:51 UTC
  • Revision ID: james.westby@ubuntu.com-20051210212551-5qwm108g7inyu2f2
Tags: upstream-0.8.10
ImportĀ upstreamĀ versionĀ 0.8.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 get.c : irssi configuration - get settings from memory
 
3
 
 
4
    Copyright (C) 1999 Timo Sirainen
 
5
 
 
6
    This program is free software; you can redistribute it and/or modify
 
7
    it under the terms of the GNU General Public License as published by
 
8
    the Free Software Foundation; either version 2 of the License, or
 
9
    (at your option) any later version.
 
10
 
 
11
    This program is distributed in the hope that it will be useful,
 
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
    GNU General Public License for more details.
 
15
 
 
16
    You should have received a copy of the GNU General Public License
 
17
    along with this program; if not, write to the Free Software
 
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
*/
 
20
 
 
21
#include "module.h"
 
22
 
 
23
CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key)
 
24
{
 
25
        GSList *tmp;
 
26
 
 
27
        g_return_val_if_fail(node != NULL, NULL);
 
28
        g_return_val_if_fail(key != NULL, NULL);
 
29
        g_return_val_if_fail(is_node_list(node), NULL);
 
30
 
 
31
        for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
 
32
                CONFIG_NODE *node = tmp->data;
 
33
 
 
34
                if (node->key != NULL && g_strcasecmp(node->key, key) == 0)
 
35
                        return node;
 
36
        }
 
37
 
 
38
        return NULL;
 
39
}
 
40
 
 
41
/* find the section from node - if not found create it unless new_type is -1.
 
42
   you can also specify in new_type if it's NODE_TYPE_LIST or NODE_TYPE_BLOCK */
 
43
CONFIG_NODE *config_node_section(CONFIG_NODE *parent, const char *key, int new_type)
 
44
{
 
45
        return config_node_section_index(parent, key, -1, new_type);
 
46
}
 
47
 
 
48
CONFIG_NODE *config_node_section_index(CONFIG_NODE *parent, const char *key,
 
49
                                       int index, int new_type)
 
50
{
 
51
        CONFIG_NODE *node;
 
52
        int nindex;
 
53
 
 
54
        g_return_val_if_fail(parent != NULL, NULL);
 
55
        g_return_val_if_fail(is_node_list(parent), NULL);
 
56
 
 
57
        node = key == NULL ? NULL : config_node_find(parent, key);
 
58
        if (node != NULL) {
 
59
                g_return_val_if_fail(new_type == -1 || new_type == node->type, NULL);
 
60
                nindex = g_slist_index(parent->value, node);
 
61
                if (index >= 0 && nindex != index &&
 
62
                    nindex <= g_slist_length(parent->value)) {
 
63
                        /* move it to wanted position */
 
64
                        parent->value = g_slist_remove(parent->value, node);
 
65
                        parent->value = g_slist_insert(parent->value, node, index);
 
66
                }
 
67
                return node;
 
68
        }
 
69
 
 
70
        if (new_type == -1)
 
71
                return NULL;
 
72
 
 
73
        node = g_new0(CONFIG_NODE, 1);
 
74
        parent->value = index < 0 ? g_slist_append(parent->value, node) :
 
75
                g_slist_insert(parent->value, node, index);
 
76
 
 
77
        node->type = new_type;
 
78
        node->key = key == NULL ? NULL : g_strdup(key);
 
79
 
 
80
        return node;
 
81
}
 
82
 
 
83
/* find the section with the whole path.
 
84
   create the path if necessary `create' is TRUE. */
 
85
CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int create)
 
86
{
 
87
        CONFIG_NODE *node;
 
88
        char **list, **tmp, *str;
 
89
        int is_list, new_type;
 
90
 
 
91
        g_return_val_if_fail(rec != NULL, NULL);
 
92
 
 
93
        if (section == NULL || *section == '\0')
 
94
                return rec->mainnode;
 
95
 
 
96
        /* check if it already exists in cache */
 
97
        node = g_hash_table_lookup(rec->cache, section);
 
98
        if (node != NULL) return node;
 
99
 
 
100
        new_type = -1;
 
101
 
 
102
        node = rec->mainnode;
 
103
        list = g_strsplit(section, "/", -1);
 
104
        for (tmp = list; *tmp != NULL; tmp++) {
 
105
                is_list = **tmp == '(';
 
106
                if (create) new_type = is_list ? NODE_TYPE_LIST : NODE_TYPE_BLOCK;
 
107
 
 
108
                node = config_node_section(node, *tmp + is_list, new_type);
 
109
                if (node == NULL) {
 
110
                        g_strfreev(list);
 
111
                        return NULL;
 
112
                }
 
113
        }
 
114
        g_strfreev(list);
 
115
 
 
116
        /* save to cache */
 
117
        str = g_strdup(section);
 
118
        g_hash_table_insert(rec->cache, str, node);
 
119
        g_hash_table_insert(rec->cache_nodes, node, str);
 
120
        return node;
 
121
}
 
122
 
 
123
char *config_get_str(CONFIG_REC *rec, const char *section, const char *key, const char *def)
 
124
{
 
125
        CONFIG_NODE *parent, *node;
 
126
        char *path;
 
127
 
 
128
        g_return_val_if_fail(rec != NULL, (char *) def);
 
129
        g_return_val_if_fail(key != NULL, (char *) def);
 
130
 
 
131
        /* check if it already exists in cache */
 
132
        path = g_strconcat(section == NULL ? "" : section, "/", key, NULL);
 
133
        node = g_hash_table_lookup(rec->cache, path);
 
134
 
 
135
        if (node != NULL)
 
136
                g_free(path);
 
137
        else {
 
138
                parent = config_node_traverse(rec, section, FALSE);
 
139
                node = parent == NULL ? NULL :
 
140
                        config_node_find(parent, key);
 
141
 
 
142
                /* save to cache */
 
143
                if (node == NULL)
 
144
                        g_free(path);
 
145
                else {
 
146
                        g_hash_table_insert(rec->cache, path, node);
 
147
                        g_hash_table_insert(rec->cache_nodes, node, path);
 
148
                }
 
149
        }
 
150
 
 
151
        return (node == NULL || !has_node_value(node)) ? (char *) def : node->value;
 
152
}
 
153
 
 
154
int config_get_int(CONFIG_REC *rec, const char *section, const char *key, int def)
 
155
{
 
156
        char *str;
 
157
 
 
158
        str = config_get_str(rec, section, key, NULL);
 
159
        if (str == NULL) return def;
 
160
 
 
161
        return atoi(str);
 
162
}
 
163
 
 
164
int config_get_bool(CONFIG_REC *rec, const char *section, const char *key, int def)
 
165
{
 
166
        char *str;
 
167
 
 
168
        str = config_get_str(rec, section, key, NULL);
 
169
        if (str == NULL) return def;
 
170
 
 
171
        return i_toupper(*str) == 'T' || i_toupper(*str) == 'Y';
 
172
}
 
173
 
 
174
char *config_node_get_str(CONFIG_NODE *parent, const char *key, const char *def)
 
175
{
 
176
        CONFIG_NODE *node;
 
177
 
 
178
        if (parent == NULL) return (char *) def;
 
179
 
 
180
        node = config_node_find(parent, key);
 
181
        return (char *) ((node != NULL && has_node_value(node)) ?
 
182
                         node->value : def);
 
183
}
 
184
 
 
185
int config_node_get_int(CONFIG_NODE *parent, const char *key, int def)
 
186
{
 
187
        char *str;
 
188
 
 
189
        str = config_node_get_str(parent, key, NULL);
 
190
        if (str == NULL) return def;
 
191
 
 
192
        return atoi(str);
 
193
}
 
194
 
 
195
int config_node_get_bool(CONFIG_NODE *parent, const char *key, int def)
 
196
{
 
197
        char *str;
 
198
 
 
199
        str = config_node_get_str(parent, key, NULL);
 
200
        if (str == NULL) return def;
 
201
 
 
202
        return i_toupper(*str) == 'T' || i_toupper(*str) == 'Y' ||
 
203
                (i_toupper(*str) == 'O' && i_toupper(str[1]) == 'N');
 
204
}
 
205
 
 
206
/* Get the value of keys `key' and `key_value' and put them to
 
207
   `ret_key' and `ret_value'. Returns -1 if not found. */
 
208
int config_node_get_keyvalue(CONFIG_NODE *node, const char *key, const char *value_key, char **ret_key, char **ret_value)
 
209
{
 
210
        CONFIG_NODE *keynode, *valuenode;
 
211
        GSList *tmp;
 
212
 
 
213
        g_return_val_if_fail(node != NULL, -1);
 
214
        g_return_val_if_fail(key != NULL, -1);
 
215
        g_return_val_if_fail(value_key != NULL, -1);
 
216
        g_return_val_if_fail(ret_key != NULL, -1);
 
217
        g_return_val_if_fail(ret_value != NULL, -1);
 
218
 
 
219
        for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
 
220
                node = tmp->data;
 
221
 
 
222
                if (node->type != NODE_TYPE_BLOCK)
 
223
                        continue;
 
224
 
 
225
                keynode = config_node_find(node, key);
 
226
                if (keynode == NULL || keynode->type != NODE_TYPE_KEY)
 
227
                        continue;
 
228
 
 
229
                valuenode = config_node_find(node, value_key);
 
230
 
 
231
                *ret_key = keynode->key;
 
232
                *ret_value = valuenode != NULL && valuenode->type == NODE_TYPE_KEY ?
 
233
                        valuenode->value : NULL;
 
234
                return 0;
 
235
        }
 
236
 
 
237
        return -1;
 
238
}
 
239
 
 
240
/* Return all values from from the list `node' in a g_strsplit() array */
 
241
char **config_node_get_list(CONFIG_NODE *node)
 
242
{
 
243
        GString *values;
 
244
        GSList *tmp;
 
245
        char **ret;
 
246
 
 
247
        g_return_val_if_fail(node != NULL, NULL);
 
248
        g_return_val_if_fail(is_node_list(node), NULL);
 
249
 
 
250
        /* put values to string */
 
251
        values = g_string_new(NULL);
 
252
        for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
 
253
                node = tmp->data;
 
254
 
 
255
                if (node->type == NODE_TYPE_VALUE)
 
256
                        g_string_sprintfa(values, "%s ", (char *) node->value);
 
257
        }
 
258
 
 
259
        /* split the values to **str array */
 
260
        if (values->len == 0)
 
261
                ret = NULL;
 
262
        else {
 
263
                g_string_truncate(values, values->len-1);
 
264
                ret = g_strsplit(values->str, " ", -1);
 
265
        }
 
266
 
 
267
        g_string_free(values, TRUE);
 
268
        return ret;
 
269
}
 
270
 
 
271
/* Returns n'th node from list. */
 
272
CONFIG_NODE *config_node_nth(CONFIG_NODE *node, int index)
 
273
{
 
274
        GSList *tmp;
 
275
 
 
276
        g_return_val_if_fail(node != NULL, NULL);
 
277
        g_return_val_if_fail(is_node_list(node), NULL);
 
278
 
 
279
        for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
 
280
                CONFIG_NODE *node = tmp->data;
 
281
 
 
282
                if (node->type != NODE_TYPE_COMMENT) {
 
283
                        if (index == 0)
 
284
                                return node;
 
285
                        index--;
 
286
                }
 
287
        }
 
288
 
 
289
        return NULL;
 
290
}
 
291
 
 
292
/* Returns index for given key */
 
293
int config_node_index(CONFIG_NODE *parent, const char *key)
 
294
{
 
295
        CONFIG_NODE *node;
 
296
        GSList *tmp;
 
297
        int index;
 
298
 
 
299
        g_return_val_if_fail(parent != NULL, -1);
 
300
        g_return_val_if_fail(key != NULL, -1);
 
301
 
 
302
        node = config_node_find(parent, key);
 
303
        if (node == NULL)
 
304
                return -1;
 
305
 
 
306
        index = 0;
 
307
        for (tmp = parent->value; tmp != NULL; tmp = tmp->next) {
 
308
                CONFIG_NODE *tmpnode = tmp->data;
 
309
 
 
310
                if (tmpnode == node)
 
311
                        return index;
 
312
 
 
313
                if (tmpnode->type != NODE_TYPE_COMMENT)
 
314
                        index++;
 
315
        }
 
316
 
 
317
        return -1;
 
318
}
 
319
 
 
320
/* Returns the first non-comment node in list */
 
321
GSList *config_node_first(GSList *list)
 
322
{
 
323
        while (list != NULL) {
 
324
                CONFIG_NODE *node = list->data;
 
325
 
 
326
                if (node->type != NODE_TYPE_COMMENT)
 
327
                        break;
 
328
                list = list->next;
 
329
        }
 
330
        return list;
 
331
}
 
332
 
 
333
/* Returns the next non-comment node in list */
 
334
GSList *config_node_next(GSList *list)
 
335
{
 
336
        list = list->next;
 
337
        return config_node_first(list);
 
338
}